/* * linux/arch/i386/nmi.c * * NMI watchdog support on APIC systems * * Started by Ingo Molnar * * Fixes: * Mikael Pettersson : AMD K7 support for local APIC NMI watchdog. * Mikael Pettersson : Power Management for local APIC NMI watchdog. * Mikael Pettersson : Pentium 4 support for local APIC NMI watchdog. * Keir Fraser : Pentium 4 Hyperthreading support */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned int nmi_watchdog = NMI_NONE; static unsigned int nmi_hz = HZ; unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ extern int logical_proc_id[]; #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) #define K7_EVNTSEL_OS (1 << 17) #define K7_EVNTSEL_USR (1 << 16) #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 #define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING #define P6_EVNTSEL0_ENABLE (1 << 22) #define P6_EVNTSEL_INT (1 << 20) #define P6_EVNTSEL_OS (1 << 17) #define P6_EVNTSEL_USR (1 << 16) #define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79 #define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED #define MSR_P4_PERFCTR0 0x300 #define MSR_P4_CCCR0 0x360 #define P4_ESCR_EVENT_SELECT(N) ((N)<<25) #define P4_ESCR_OS0 (1<<3) #define P4_ESCR_USR0 (1<<2) #define P4_ESCR_OS1 (1<<1) #define P4_ESCR_USR1 (1<<0) #define P4_CCCR_OVF_PMI0 (1<<26) #define P4_CCCR_OVF_PMI1 (1<<27) #define P4_CCCR_THRESHOLD(N) ((N)<<20) #define P4_CCCR_COMPLEMENT (1<<19) #define P4_CCCR_COMPARE (1<<18) #define P4_CCCR_REQUIRED (3<<16) #define P4_CCCR_ESCR_SELECT(N) ((N)<<13) #define P4_CCCR_ENABLE (1<<12) /* * Set up IQ_COUNTER{0,1} to behave like a clock, by having IQ_CCCR{0,1} filter * CRU_ESCR0 (with any non-null event selector) through a complemented * max threshold. [IA32-Vol3, Section 14.9.9] */ #define MSR_P4_IQ_COUNTER0 0x30C #define MSR_P4_IQ_COUNTER1 0x30D #define MSR_P4_IQ_CCCR0 0x36C #define MSR_P4_IQ_CCCR1 0x36D #define MSR_P4_CRU_ESCR0 0x3B8 /* ESCR no. 4 */ #define P4_NMI_CRU_ESCR0 \ (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS0|P4_ESCR_USR0| \ P4_ESCR_OS1|P4_ESCR_USR1) #define P4_NMI_IQ_CCCR0 \ (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) #define P4_NMI_IQ_CCCR1 \ (P4_CCCR_OVF_PMI1|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) int __init check_nmi_watchdog (void) { unsigned int prev_nmi_count[NR_CPUS]; int cpu; if ( !nmi_watchdog ) return 0; printk("Testing NMI watchdog --- "); for ( cpu = 0; cpu < smp_num_cpus; cpu++ ) prev_nmi_count[cpu] = nmi_count(cpu); __sti(); mdelay((10*1000)/nmi_hz); /* wait 10 ticks */ for ( cpu = 0; cpu < smp_num_cpus; cpu++ ) { if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 ) printk("CPU#%d stuck. ", cpu); else printk("CPU#%d okay. ", cpu); } printk("\n"); /* now that we know it works we can reduce NM
#include "bootloader.h"


void bootloader_jump(void) {}
TPC, APIC_DM_NMI); wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1); } } else { wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); } } }