[RFC PATCH 4/6] x86/apic: Make the APIC mode setup earlier for SMP-capable system

From: Dou Liyang
Date: Wed Mar 29 2017 - 10:56:47 EST


In the SMP-capable system, enable and setup the APIC mode in
native_smp_prepare_boot_cpu() which almost be called at the end
of start_kernel().

The MP table or ACPI has been read earlier, and time_init() which
is called before the APIC mode setup may need the IRQ.

Move the APIC mode setup code to init_IRQ(). Do it at the end of
IRQ initialization for SMP-capable system.

Signed-off-by: Dou Liyang <douly.fnst@xxxxxxxxxxxxxx>
---
arch/x86/include/asm/apic.h | 3 ++-
arch/x86/kernel/apic/apic.c | 39 ++++++++++++++++++++++++++++++++-------
arch/x86/kernel/smpboot.c | 10 +---------
3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index c973f18..be2abc3 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -146,7 +146,8 @@ static inline int apic_force_enable(unsigned long addr)
extern int apic_force_enable(unsigned long addr);
#endif

-extern int apic_bsp_setup(bool upmode);
+extern int apic_bsp_timer_setup(void);
+extern void apic_bsp_setup(bool upmode);
extern void apic_ap_setup(void);

/*
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 0ba8a85..ce8f88d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1157,6 +1157,7 @@ enum apic_bsp_mode {
APIC_BSP_MODEL_PIC = 0,
APIC_BSP_MODEL_VIRTUAL_WIRE,
APIC_BSP_MODEL_SYMMETRIC_IO,
+ APIC_BSP_MODEL_SYMMETRIC_IO_NO_ROUTING,
APIC_BSP_MODEL_COUNT
};

@@ -1207,7 +1208,29 @@ static int __init apic_bsp_mode_check(void)

/* Other checks of ACPI options will be done in each setup function */

+#ifdef CONFIG_SMP
+ if (read_apic_id() != boot_cpu_physical_apicid) {
+ pr_info("Boot APIC ID in local APIC unexpected (%d vs %d)",
+ read_apic_id(), boot_cpu_physical_apicid);
+
+ disable_ioapic_support();
+ /*Do nothing, just switch back to PIC here */
+ return APIC_BSP_MODEL_PIC;
+ }
+
+ /*
+ * If SMP should be disabled, then really disable it!
+ * No need setup apic routing ?
+ */
+ if (!setup_max_cpus) {
+ pr_info("SMP mode deactivated\n");
+ return APIC_BSP_MODEL_SYMMETRIC_IO_NO_ROUTING;
+ }
+
return APIC_BSP_MODEL_SYMMETRIC_IO;
+#else
+ return APIC_BSP_MODEL_PIC;
+#endif
}

/*
@@ -1271,6 +1294,12 @@ void __init init_bsp_APIC(void)
return;
case APIC_BSP_MODEL_SYMMETRIC_IO:
pr_info("switch to symmectic I/O model.\n");
+ default_setup_apic_routing();
+ apic_bsp_setup(false);
+ return;
+ case APIC_BSP_MODEL_SYMMETRIC_IO_NO_ROUTING:
+ pr_info("switch to symmectic I/O model with no apic routing.\n");
+ apic_bsp_setup(false);
return;
}
}
@@ -2325,7 +2354,7 @@ static void __init apic_bsp_up_setup(void)
}

/* Setup local APIC timer and get the Id*/
-static int __init apic_bsp_timer_setup(void)
+int __init apic_bsp_timer_setup(void)
{
int id;

@@ -2350,10 +2379,8 @@ static int __init apic_bsp_timer_setup(void)
* Returns:
* apic_id of BSP APIC
*/
-int __init apic_bsp_setup(bool upmode)
+void __init apic_bsp_setup(bool upmode)
{
- int id;
-
connect_bsp_APIC();
if (upmode)
apic_bsp_up_setup();
@@ -2363,9 +2390,6 @@ int __init apic_bsp_setup(bool upmode)
end_local_APIC_setup();
irq_remap_enable_fault_handling();
setup_IO_APIC();
-
- id = apic_bsp_timer_setup();
- return id;
}

/*
@@ -2404,6 +2428,7 @@ int __init APIC_init_uniprocessor(void)

default_setup_apic_routing();
apic_bsp_setup(true);
+ apic_bsp_timer_setup();
return 0;
}

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index bd1f1ad..a556281 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1332,20 +1332,12 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
return;
case SMP_FORCE_UP:
disable_smp();
- apic_bsp_setup(false);
return;
case SMP_OK:
break;
}

- if (read_apic_id() != boot_cpu_physical_apicid) {
- panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
- read_apic_id(), boot_cpu_physical_apicid);
- /* Or can we switch back to PIC here? */
- }
-
- default_setup_apic_routing();
- cpu0_logical_apicid = apic_bsp_setup(false);
+ cpu0_logical_apicid = apic_bsp_timer_setup();

pr_info("CPU0: ");
print_cpu_info(&cpu_data(0));
--
2.5.5