• Yinghai Lu's avatar
    x86: fix wakeup_cpu with numaq/es7000, v2 · 569712b2
    Yinghai Lu authored
    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: default avatarYinghai Lu <yinghai@kernel.org>
    Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
    569712b2
apic.h 4.31 KB