x86, apic: Introduce .apicdrivers section to find the list of apic drivers
authorSuresh Siddha <suresh.b.siddha@intel.com>
Sat, 21 May 2011 00:51:17 +0000 (17:51 -0700)
committerIngo Molnar <mingo@elte.hu>
Sun, 22 May 2011 09:48:03 +0000 (11:48 +0200)
This will pave the way for each apic driver to be self-contained
and eliminate the need for apic_probe[].

Order in which apic drivers are listed in the .apicdrivers
section is important, as this determines the apic probe order.
And this is enforced by the ordering of apic driver files in the
Makefile and the macros apic_driver()/apic_drivers().

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Tested-by: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: steiner@sgi.com
Cc: gorcunov@openvz.org
Cc: yinghai@kernel.org
Link: http://lkml.kernel.org/r/20110521005526.068775085@sbsiddha-MOBL3.sc.intel.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
12 files changed:
arch/x86/include/asm/apic.h
arch/x86/kernel/apic/Makefile
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/apic/summit_32.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/vmlinux.lds.S

index a0c46f0612106a220cd01f4d6fe81df61eeecb70..80b243c7f0f0fc3f40e8c829fa8d931270141003 100644 (file)
@@ -380,6 +380,26 @@ struct apic {
  */
 extern struct apic *apic;
 
+/*
+ * APIC drivers are probed based on how they are listed in the .apicdrivers
+ * section. So the order is important and enforced by the ordering
+ * of different apic driver files in the Makefile.
+ *
+ * For the files having two apic drivers, we use apic_drivers()
+ * to enforce the order with in them.
+ */
+#define apic_driver(sym)                                       \
+       static struct apic *__apicdrivers_##sym __used          \
+       __aligned(sizeof(struct apic *))                        \
+       __section(.apicdrivers) = { &sym }
+
+#define apic_drivers(sym1, sym2)                                       \
+       static struct apic *__apicdrivers_##sym1##sym2[2] __used        \
+       __aligned(sizeof(struct apic *))                                \
+       __section(.apicdrivers) = { &sym1, &sym2 }
+
+extern struct apic *__apicdrivers[], *__apicdrivers_end[];
+
 /*
  * APIC functionality to boot other CPUs - only used on SMP:
  */
index 3966b564ea478746bc77d66886249a294177b21a..767fd04f2843ee1d097ac05f7937a9829a648a23 100644 (file)
@@ -2,20 +2,25 @@
 # Makefile for local APIC drivers and for the IO-APIC code
 #
 
-obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o apic_noop.o probe_$(BITS).o ipi.o
+obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o apic_noop.o ipi.o
 obj-y                          += hw_nmi.o
 
 obj-$(CONFIG_X86_IO_APIC)      += io_apic.o
 obj-$(CONFIG_SMP)              += ipi.o
 
 ifeq ($(CONFIG_X86_64),y)
-obj-y                          += apic_flat_64.o
-obj-$(CONFIG_X86_X2APIC)       += x2apic_cluster.o
-obj-$(CONFIG_X86_X2APIC)       += x2apic_phys.o
+# APIC probe will depend on the listing order here
 obj-$(CONFIG_X86_UV)           += x2apic_uv_x.o
+obj-$(CONFIG_X86_X2APIC)       += x2apic_phys.o
+obj-$(CONFIG_X86_X2APIC)       += x2apic_cluster.o
+obj-y                          += apic_flat_64.o
 endif
 
-obj-$(CONFIG_X86_BIGSMP)       += bigsmp_32.o
+# APIC probe will depend on the listing order here
 obj-$(CONFIG_X86_NUMAQ)                += numaq_32.o
-obj-$(CONFIG_X86_ES7000)       += es7000_32.o
 obj-$(CONFIG_X86_SUMMIT)       += summit_32.o
+obj-$(CONFIG_X86_BIGSMP)       += bigsmp_32.o
+obj-$(CONFIG_X86_ES7000)       += es7000_32.o
+
+# For 32bit, probe_32 need to be listed last
+obj-$(CONFIG_X86_LOCAL_APIC)   += probe_$(BITS).o
index 025921f03eb37d331f72d87513a69b4e595a0a34..6ce0f7f08c5712f8b6a4fdd39dcbaa66639c642d 100644 (file)
@@ -377,3 +377,8 @@ struct apic apic_physflat =  {
        .wait_icr_idle                  = native_apic_wait_icr_idle,
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 };
+
+/*
+ * We need to check for physflat first, so this order is important.
+ */
+apic_drivers(apic_physflat, apic_flat);
index d84ac5a584b511291e7677bca5f11caf457435b7..cfb13c3e545110a5f7efdfceb1bade733d35a07d 100644 (file)
@@ -254,3 +254,5 @@ struct apic apic_bigsmp = {
 
        .x86_32_early_logical_apicid    = bigsmp_early_logical_apicid,
 };
+
+apic_driver(apic_bigsmp);
index 70533de5bd29741c41b03b1cc8c989740c4ff15c..80de0d78cbcac854b1feb5c30a1ee30e6559efdc 100644 (file)
@@ -747,3 +747,9 @@ struct apic __refdata apic_es7000 = {
 
        .x86_32_early_logical_apicid    = es7000_early_logical_apicid,
 };
+
+/*
+ * Need to check for es7000 followed by es7000_cluster, so this order
+ * in apic_drivers is important.
+ */
+apic_drivers(apic_es7000, apic_es7000_cluster);
index 30f13319e24b82f81a85d9de989a24024083af8c..4caab0d13d990ee69a34cf80c24aa10ac74eaf16 100644 (file)
@@ -537,3 +537,5 @@ struct apic __refdata apic_numaq = {
        .x86_32_early_logical_apicid    = noop_x86_32_early_logical_apicid,
        .x86_32_numa_cpu_node           = numaq_numa_cpu_node,
 };
+
+apic_driver(apic_numaq);
index 6541e471fd9195535a6198efa87d738ee25afbba..a319b33cfc1480f02b55f7357e9d9065184d29c8 100644 (file)
@@ -174,6 +174,8 @@ struct apic apic_default = {
        .x86_32_early_logical_apicid    = default_x86_32_early_logical_apicid,
 };
 
+apic_driver(apic_default);
+
 extern struct apic apic_numaq;
 extern struct apic apic_summit;
 extern struct apic apic_bigsmp;
index 35bcd7d995a137ecd98cb30c510418b725bf001c..447ec0fa9aa12b40f69dd0ee48f20fae3ef2122b 100644 (file)
@@ -552,3 +552,5 @@ struct apic apic_summit = {
 
        .x86_32_early_logical_apicid    = summit_early_logical_apicid,
 };
+
+apic_driver(apic_summit);
index f7875d9a18c27371fa4674af25a020317d54479e..7595c5775a548063638d796ae9119794dc718487 100644 (file)
@@ -264,3 +264,5 @@ struct apic apic_x2apic_cluster = {
        .wait_icr_idle                  = native_x2apic_wait_icr_idle,
        .safe_wait_icr_idle             = native_safe_x2apic_wait_icr_idle,
 };
+
+apic_driver(apic_x2apic_cluster);
index 78c8f33a09faf4c678e05800e8802319b915504d..f7ba21cb3e25649a775229171a226d82a9aa3849 100644 (file)
@@ -168,3 +168,5 @@ struct apic apic_x2apic_phys = {
        .wait_icr_idle                  = native_x2apic_wait_icr_idle,
        .safe_wait_icr_idle             = native_safe_x2apic_wait_icr_idle,
 };
+
+apic_driver(apic_x2apic_phys);
index 6bb80b1c8a7acda8177266518daeefe13df633bd..b6c629838f0080dea6a640e901df74868fdc3459 100644 (file)
@@ -864,3 +864,5 @@ void __init uv_system_init(void)
        if (is_kdump_kernel())
                reboot_type = BOOT_ACPI;
 }
+
+apic_driver(apic_x2apic_uv_x);
index 624a2016198ef9317992069aaf676da19e5bd6b9..49927a863cc18089d1f1ab156c63e1080af841d7 100644 (file)
@@ -305,6 +305,13 @@ SECTIONS
                __iommu_table_end = .;
        }
 
+       . = ALIGN(8);
+       .apicdrivers : AT(ADDR(.apicdrivers) - LOAD_OFFSET) {
+               __apicdrivers = .;
+               *(.apicdrivers);
+               __apicdrivers_end = .;
+       }
+
        . = ALIGN(8);
        /*
         * .exit.text is discard at runtime, not link time, to deal with