2005-04-17 02:20:36 +04:00
/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
* which needs to alter them . */
static inline void smpboot_clear_io_apic_irqs ( void )
{
2008-07-10 17:09:04 +04:00
# ifdef CONFIG_X86_IO_APIC
2005-04-17 02:20:36 +04:00
io_apic_irqs = 0 ;
2008-07-10 17:09:04 +04:00
# endif
2005-04-17 02:20:36 +04:00
}
static inline void smpboot_setup_warm_reset_vector ( unsigned long start_eip )
{
2011-07-19 14:39:03 +04:00
unsigned long flags ;
spin_lock_irqsave ( & rtc_lock , flags ) ;
2005-04-17 02:20:36 +04:00
CMOS_WRITE ( 0xa , 0xf ) ;
2011-07-19 14:39:03 +04:00
spin_unlock_irqrestore ( & rtc_lock , flags ) ;
2005-04-17 02:20:36 +04:00
local_flush_tlb ( ) ;
2008-07-21 23:35:38 +04:00
pr_debug ( " 1. \n " ) ;
2009-01-28 18:09:23 +03:00
* ( ( volatile unsigned short * ) phys_to_virt ( apic - > trampoline_phys_high ) ) =
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>
2008-11-16 14:12:49 +03:00
start_eip > > 4 ;
2008-07-21 23:35:38 +04:00
pr_debug ( " 2. \n " ) ;
2009-01-28 18:09:23 +03:00
* ( ( volatile unsigned short * ) phys_to_virt ( apic - > trampoline_phys_low ) ) =
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>
2008-11-16 14:12:49 +03:00
start_eip & 0xf ;
2008-07-21 23:35:38 +04:00
pr_debug ( " 3. \n " ) ;
2005-04-17 02:20:36 +04:00
}
static inline void smpboot_restore_warm_reset_vector ( void )
{
2011-07-19 14:39:03 +04:00
unsigned long flags ;
2005-04-17 02:20:36 +04:00
/*
* Install writable page 0 entry to set BIOS data area .
*/
local_flush_tlb ( ) ;
/*
* Paranoid : Set warm reset code and vector here back
* to default values .
*/
2011-07-19 14:39:03 +04:00
spin_lock_irqsave ( & rtc_lock , flags ) ;
2005-04-17 02:20:36 +04:00
CMOS_WRITE ( 0 , 0xf ) ;
2011-07-19 14:39:03 +04:00
spin_unlock_irqrestore ( & rtc_lock , flags ) ;
2005-04-17 02:20:36 +04:00
2011-02-08 07:25:00 +03:00
* ( ( volatile u32 * ) phys_to_virt ( apic - > trampoline_phys_low ) ) = 0 ;
2005-04-17 02:20:36 +04:00
}
2008-04-11 15:28:49 +04:00
static inline void __init smpboot_setup_io_apic ( void )
2005-04-17 02:20:36 +04:00
{
2008-07-10 17:09:04 +04:00
# ifdef CONFIG_X86_IO_APIC
2005-04-17 02:20:36 +04:00
/*
* Here we can be sure that there is an IO - APIC in the system . Let ' s
* go and set it up :
*/
if ( ! skip_ioapic_setup & & nr_ioapics )
setup_IO_APIC ( ) ;
2008-06-06 06:28:13 +04:00
else {
2008-03-19 20:26:06 +03:00
nr_ioapics = 0 ;
2008-06-06 06:28:13 +04:00
}
2008-07-10 17:09:04 +04:00
# endif
2005-04-17 02:20:36 +04:00
}
2008-03-19 20:26:10 +03:00
static inline void smpboot_clear_io_apic ( void )
{
2008-07-10 17:09:04 +04:00
# ifdef CONFIG_X86_IO_APIC
2008-03-19 20:26:10 +03:00
nr_ioapics = 0 ;
2008-07-10 17:09:04 +04:00
# endif
2008-03-19 20:26:10 +03:00
}