aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/smpboot.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2008-11-16 06:12:49 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-17 11:57:34 -0500
commit569712b2b0970fa5b19673544d62ae661d04a220 (patch)
tree2bfd507fe1ab746115586d556ec9624d36d16337 /arch/x86/kernel/smpboot.c
parente14c8bf86350f6c39186a139c5c584a6111b2f01 (diff)
x86: fix wakeup_cpu with numaq/es7000, v2
Impact: fix secondary-CPU wakeup/init path with numaq and es7000 While looking at wakeup_secondary_cpu for WAKE_SECONDARY_VIA_NMI: |#ifdef WAKE_SECONDARY_VIA_NMI |/* | * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this | * won't ... remember to clear down the APIC, etc later. | */ |static int __devinit |wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) |{ | unsigned long send_status, accept_status = 0; | int maxlvt; |... | if (APIC_INTEGRATED(apic_version[phys_apicid])) { | maxlvt = lapic_get_maxlvt(); I noticed that there is no warning about undefined phys_apicid... because WAKE_SECONDARY_VIA_NMI and WAKE_SECONDARY_VIA_INIT can not be defined at the same time. So NUMAQ is using wrong wakeup_secondary_cpu. WAKE_SECONDARY_VIA_NMI, WAKE_SECONDARY_VIA_INIT and WAKE_SECONDARY_VIA_MIP are variants of a weird and fragile preprocessor-driven "HAL" mechanisms to specify the kind of secondary-CPU wakeup strategy a given x86 kernel will use. The vast majority of systems want to use INIT for secondary wakeup - NUMAQ uses an NMI, (old-style-) ES7000 uses 'MIP' (a firmware driven in-memory flag to let secondaries continue). So convert these mechanisms to x86_quirks and add a ->wakeup_secondary_cpu() method to specify the rare exception to the sane default. Extend genapic accordingly as well, for 32-bit. While looking further, I noticed that functions in wakecup.h for numaq and es7000 are different to the default in mach_wakecpu.h - but smpboot.c will only use default mach_wakecpu.h with smphook.h. So we need to add mach_wakecpu.h for mach_generic, to properly support numaq and es7000, and vectorize the following SMP init methods: int trampoline_phys_low; int trampoline_phys_high; void (*wait_for_init_deassert)(atomic_t *deassert); void (*smp_callin_clear_local_apic)(void); void (*store_NMI_vector)(unsigned short *high, unsigned short *low); void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); void (*inquire_remote_apic)(int apicid); Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r--arch/x86/kernel/smpboot.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 7b1093397319..498c1ef37fe0 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -62,6 +62,7 @@
62#include <asm/mtrr.h> 62#include <asm/mtrr.h>
63#include <asm/vmi.h> 63#include <asm/vmi.h>
64#include <asm/genapic.h> 64#include <asm/genapic.h>
65#include <asm/setup.h>
65#include <linux/mc146818rtc.h> 66#include <linux/mc146818rtc.h>
66 67
67#include <mach_apic.h> 68#include <mach_apic.h>
@@ -536,7 +537,7 @@ static void impress_friends(void)
536 pr_debug("Before bogocount - setting activated=1.\n"); 537 pr_debug("Before bogocount - setting activated=1.\n");
537} 538}
538 539
539static inline void __inquire_remote_apic(int apicid) 540void __inquire_remote_apic(int apicid)
540{ 541{
541 unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; 542 unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
542 char *names[] = { "ID", "VERSION", "SPIV" }; 543 char *names[] = { "ID", "VERSION", "SPIV" };
@@ -575,14 +576,13 @@ static inline void __inquire_remote_apic(int apicid)
575 } 576 }
576} 577}
577 578
578#ifdef WAKE_SECONDARY_VIA_NMI
579/* 579/*
580 * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal 580 * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
581 * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this 581 * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
582 * won't ... remember to clear down the APIC, etc later. 582 * won't ... remember to clear down the APIC, etc later.
583 */ 583 */
584static int __devinit 584int __devinit
585wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) 585wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
586{ 586{
587 unsigned long send_status, accept_status = 0; 587 unsigned long send_status, accept_status = 0;
588 int maxlvt; 588 int maxlvt;
@@ -599,7 +599,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
599 * Give the other CPU some time to accept the IPI. 599 * Give the other CPU some time to accept the IPI.
600 */ 600 */
601 udelay(200); 601 udelay(200);
602 if (APIC_INTEGRATED(apic_version[phys_apicid])) { 602 if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
603 maxlvt = lapic_get_maxlvt(); 603 maxlvt = lapic_get_maxlvt();
604 if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ 604 if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
605 apic_write(APIC_ESR, 0); 605 apic_write(APIC_ESR, 0);
@@ -614,11 +614,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
614 614
615 return (send_status | accept_status); 615 return (send_status | accept_status);
616} 616}
617#endif /* WAKE_SECONDARY_VIA_NMI */
618 617
619#ifdef WAKE_SECONDARY_VIA_INIT
620static int __devinit 618static int __devinit
621wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) 619wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
622{ 620{
623 unsigned long send_status, accept_status = 0; 621 unsigned long send_status, accept_status = 0;
624 int maxlvt, num_starts, j; 622 int maxlvt, num_starts, j;
@@ -737,7 +735,15 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
737 735
738 return (send_status | accept_status); 736 return (send_status | accept_status);
739} 737}
740#endif /* WAKE_SECONDARY_VIA_INIT */ 738
739static int __devinit
740wakeup_secondary_cpu(int apicid, unsigned long start_eip)
741{
742 if (x86_quirks->wakeup_secondary_cpu)
743 return x86_quirks->wakeup_secondary_cpu(apicid, start_eip);
744
745 return wakeup_secondary_cpu_via_init(apicid, start_eip);
746}
741 747
742struct create_idle { 748struct create_idle {
743 struct work_struct work; 749 struct work_struct work;