[PATCH] x86, apic: Add unset_bsp parameter to unset BSP flag at boottime

From: HATAYAMA Daisuke
Date: Fri Mar 15 2013 - 03:28:01 EST


On crash dump, multiple CPUs are useful for CPU-bound processing like
compression and even for IO-bound processing like disk IO to make
improvement of IO-multiplication proportional to the number of disks.

However, we cannot wakeup the 2nd and later cpus in the kdump 2nd
kernel now if crash happens on AP. If crash happens on AP, kexec
enters the 2nd kernel with the AP, and there BSP in the 1st kernel is
expected to be haling in the 1st kernel or possibly in any fatal
system error state.

To wake up CPUs, we use the method called INIT-INIT-SIPI. But, INIT to
the CPU with BSP flag set causes it to jump into BIOS init code. A
typical visible behaviour is system hang or immediate system reset,
depending on the BIOS init code.

AP can be initiated by INIT even in a fatal state: MP spec explains
that processor-specific INIT can be used to recover AP from a fatal
system error. On the other hand, there's no method for the CPU with
BSP flag set to recover.

This patch add unset_bsp kernel parameter and if it's specified, BSP
flag of boot CPU is unset, expecting all the CPUS to keep BSP unset
throught runtime.

Signed-off-by: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx>
---
arch/x86/include/asm/apic.h | 3 +++
arch/x86/kernel/apic/apic.c | 25 +++++++++++++++++++++++++
arch/x86/kernel/setup.c | 2 ++
3 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 3388034..b9cd9a9 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -262,6 +262,8 @@ static inline int apic_is_clustered_box(void)

extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);

+extern void do_unset_bsp_flag(void);
+
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
@@ -269,6 +271,7 @@ static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop
+static inline void unset_bsp_flag(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 904611b..a34bd75 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2544,3 +2544,28 @@ static int __init lapic_insert_resource(void)
* that is using request_resource
*/
late_initcall(lapic_insert_resource);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+static int unset_bsp_flag __initdata;
+
+void __init do_unset_bsp_flag(void)
+{
+ if (!unset_bsp_flag)
+ return;
+
+ if (cpu_has_apic) {
+ u32 l, h;
+
+ rdmsr_safe(MSR_IA32_APICBASE, &l, &h);
+ l &= ~MSR_IA32_APICBASE_BSP;
+ wrmsr_safe(MSR_IA32_APICBASE, l, h);
+ }
+}
+
+static int __init parse_unset_bsp(char *arg)
+{
+ unset_bsp_flag = 1;
+ return 0;
+}
+early_param("unset_bsp", parse_unset_bsp);
+#endif
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 90d8cc9..62a5f2e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1165,6 +1165,8 @@ void __init setup_arch(char **cmdline_p)
if (x86_io_apic_ops.init)
x86_io_apic_ops.init();

+ do_unset_bsp_flag();
+
kvm_guest_init();

e820_reserve_resources();
--
1.7.7.6


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/