diff options
author | Yinghai Lu <yinghai@kernel.org> | 2008-11-16 06:12:49 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-17 11:57:34 -0500 |
commit | 569712b2b0970fa5b19673544d62ae661d04a220 (patch) | |
tree | 2bfd507fe1ab746115586d556ec9624d36d16337 /arch/x86/kernel/es7000_32.c | |
parent | e14c8bf86350f6c39186a139c5c584a6111b2f01 (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/es7000_32.c')
-rw-r--r-- | arch/x86/kernel/es7000_32.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index f454c78fcef6..bed10dddf099 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/smp.h> | 40 | #include <asm/smp.h> |
41 | #include <asm/apicdef.h> | 41 | #include <asm/apicdef.h> |
42 | #include <mach_mpparse.h> | 42 | #include <mach_mpparse.h> |
43 | #include <asm/setup.h> | ||
43 | 44 | ||
44 | /* | 45 | /* |
45 | * ES7000 chipsets | 46 | * ES7000 chipsets |
@@ -161,6 +162,26 @@ es7000_rename_gsi(int ioapic, int gsi) | |||
161 | return gsi; | 162 | return gsi; |
162 | } | 163 | } |
163 | 164 | ||
165 | #ifdef CONFIG_ES7000_CLUSTERED_APIC | ||
166 | static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) | ||
167 | { | ||
168 | unsigned long vect = 0, psaival = 0; | ||
169 | |||
170 | if (psai == NULL) | ||
171 | return -1; | ||
172 | |||
173 | vect = ((unsigned long)__pa(eip)/0x1000) << 16; | ||
174 | psaival = (0x1000000 | vect | cpu); | ||
175 | |||
176 | while (*psai & 0x1000000) | ||
177 | ; | ||
178 | |||
179 | *psai = psaival; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | #endif | ||
184 | |||
164 | void __init | 185 | void __init |
165 | setup_unisys(void) | 186 | setup_unisys(void) |
166 | { | 187 | { |
@@ -176,6 +197,9 @@ setup_unisys(void) | |||
176 | else | 197 | else |
177 | es7000_plat = ES7000_CLASSIC; | 198 | es7000_plat = ES7000_CLASSIC; |
178 | ioapic_renumber_irq = es7000_rename_gsi; | 199 | ioapic_renumber_irq = es7000_rename_gsi; |
200 | #ifdef CONFIG_ES7000_CLUSTERED_APIC | ||
201 | x86_quirks->wakeup_secondary_cpu = wakeup_secondary_cpu_via_mip; | ||
202 | #endif | ||
179 | } | 203 | } |
180 | 204 | ||
181 | /* | 205 | /* |
@@ -324,26 +348,6 @@ es7000_mip_write(struct mip_reg *mip_reg) | |||
324 | return status; | 348 | return status; |
325 | } | 349 | } |
326 | 350 | ||
327 | int | ||
328 | es7000_start_cpu(int cpu, unsigned long eip) | ||
329 | { | ||
330 | unsigned long vect = 0, psaival = 0; | ||
331 | |||
332 | if (psai == NULL) | ||
333 | return -1; | ||
334 | |||
335 | vect = ((unsigned long)__pa(eip)/0x1000) << 16; | ||
336 | psaival = (0x1000000 | vect | cpu); | ||
337 | |||
338 | while (*psai & 0x1000000) | ||
339 | ; | ||
340 | |||
341 | *psai = psaival; | ||
342 | |||
343 | return 0; | ||
344 | |||
345 | } | ||
346 | |||
347 | void __init | 351 | void __init |
348 | es7000_sw_apic(void) | 352 | es7000_sw_apic(void) |
349 | { | 353 | { |