ccc3c3192a
Machine checks support waking up the mcelog daemon quickly. The original wake up code for this was pretty ugly, relying on a idle notifier and a special process flag. The reason it did it this way is that the machine check handler is not subject to normal interrupt locking rules so it's not safe to call wake_up(). Instead it set a process flag and then either did the wakeup in the syscall return or in the idle notifier. This patch adds a new "bootstraping" method as replacement. The idea is that the handler checks if it's in a state where it is unsafe to call wake_up(). If it's safe it calls it directly. When it's not safe -- that is it interrupted in a critical section with interrupts disables -- it uses a new "self IPI" to trigger an IPI to its own CPU. This can be done safely because IPI triggers are atomic with some care. The IPI is raised once the interrupts are reenabled and can then safely call wake_up(). When APICs are disabled the event is just queued and will be picked up eventually by the next polling timer. I think that's a reasonable compromise, since it should only happen quite rarely. Contains fixes from Ying Huang. [ solve conflict on irqinit, make it work on 32bit (entry_arch.h) - HS ] Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
67 lines
2.3 KiB
C
67 lines
2.3 KiB
C
/*
|
|
* This file is designed to contain the BUILD_INTERRUPT specifications for
|
|
* all of the extra named interrupt vectors used by the architecture.
|
|
* Usually this is the Inter Process Interrupts (IPIs)
|
|
*/
|
|
|
|
/*
|
|
* The following vectors are part of the Linux architecture, there
|
|
* is no hardware IRQ pin equivalent for them, they are triggered
|
|
* through the ICC by us (IPIs)
|
|
*/
|
|
#ifdef CONFIG_SMP
|
|
BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
|
|
BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
|
|
BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
|
|
BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
|
|
|
|
BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt1,INVALIDATE_TLB_VECTOR_START+1,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt2,INVALIDATE_TLB_VECTOR_START+2,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt3,INVALIDATE_TLB_VECTOR_START+3,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt4,INVALIDATE_TLB_VECTOR_START+4,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt5,INVALIDATE_TLB_VECTOR_START+5,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt6,INVALIDATE_TLB_VECTOR_START+6,
|
|
smp_invalidate_interrupt)
|
|
BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7,
|
|
smp_invalidate_interrupt)
|
|
#endif
|
|
|
|
BUILD_INTERRUPT(generic_interrupt, GENERIC_INTERRUPT_VECTOR)
|
|
|
|
/*
|
|
* every pentium local APIC has two 'local interrupts', with a
|
|
* soft-definable vector attached to both interrupts, one of
|
|
* which is a timer interrupt, the other one is error counter
|
|
* overflow. Linux uses the local APIC timer interrupt to get
|
|
* a much simpler SMP time architecture:
|
|
*/
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
|
|
BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
|
|
BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
|
|
|
|
#ifdef CONFIG_PERF_COUNTERS
|
|
BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR)
|
|
#endif
|
|
|
|
#ifdef CONFIG_X86_THERMAL_VECTOR
|
|
BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
|
|
#endif
|
|
|
|
#ifdef CONFIG_X86_MCE_THRESHOLD
|
|
BUILD_INTERRUPT(threshold_interrupt,THRESHOLD_APIC_VECTOR)
|
|
#endif
|
|
|
|
#ifdef CONFIG_X86_NEW_MCE
|
|
BUILD_INTERRUPT(mce_self_interrupt,MCE_SELF_VECTOR)
|
|
#endif
|
|
|
|
#endif
|