[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Clean up NMI watchdog handler. No need to hack into ac_timer structs.
ChangeSet 1.1566, 2005/05/26 17:09:52+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx Clean up NMI watchdog handler. No need to hack into ac_timer structs. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> arch/x86/nmi.c | 121 +++++++++++++++++++++++-------------------------- arch/x86/setup.c | 6 -- common/ac_timer.c | 10 +++- include/xen/ac_timer.h | 14 ----- 4 files changed, 67 insertions(+), 84 deletions(-) diff -Nru a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c --- a/xen/arch/x86/nmi.c 2005-05-26 13:03:55 -04:00 +++ b/xen/arch/x86/nmi.c 2005-05-26 13:03:55 -04:00 @@ -29,9 +29,10 @@ 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[]; +static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ +static unsigned int nmi_p4_cccr_val; +static struct ac_timer nmi_timer[NR_CPUS]; +static unsigned int nmi_timer_ticks[NR_CPUS]; #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) @@ -50,10 +51,6 @@ #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) @@ -63,24 +60,17 @@ #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 + * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 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_CRU_ESCR0 P4_ESCR_EVENT_SELECT(0x3F) #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) { @@ -118,6 +108,13 @@ return 0; } +static void nmi_timer_fn(void *unused) +{ + int cpu = smp_processor_id(); + nmi_timer_ticks[cpu]++; + set_ac_timer(&nmi_timer[cpu], NOW() + MILLISECS(1000)); +} + static inline void nmi_pm_init(void) { } #define __pminit __init @@ -186,45 +183,35 @@ return 0; nmi_perfctr_msr = MSR_P4_IQ_COUNTER0; - - if ( logical_proc_id[smp_processor_id()] == 0 ) - { - if (!(misc_enable & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL)) - clear_msr_range(0x3F1, 2); - /* MSR 0x3F0 seems to have a default value of 0xFC00, but current - docs doesn't fully define it, so leave it alone for now. */ - clear_msr_range(0x3A0, 31); - clear_msr_range(0x3C0, 6); - clear_msr_range(0x3C8, 6); - clear_msr_range(0x3E0, 2); - clear_msr_range(MSR_P4_CCCR0, 18); - clear_msr_range(MSR_P4_PERFCTR0, 18); + nmi_p4_cccr_val = P4_NMI_IQ_CCCR0; + if ( smp_num_siblings == 2 ) + nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1; + + if (!(misc_enable & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL)) + clear_msr_range(0x3F1, 2); + /* MSR 0x3F0 seems to have a default value of 0xFC00, but current + docs doesn't fully define it, so leave it alone for now. */ + clear_msr_range(0x3A0, 31); + clear_msr_range(0x3C0, 6); + clear_msr_range(0x3C8, 6); + clear_msr_range(0x3E0, 2); + clear_msr_range(MSR_P4_CCCR0, 18); + clear_msr_range(MSR_P4_PERFCTR0, 18); - wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0); - wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0); - Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000)); - wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1); - apic_write(APIC_LVTPC, APIC_DM_NMI); - wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0); - } - else if ( logical_proc_id[smp_processor_id()] == 1 ) - { - wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1 & ~P4_CCCR_ENABLE, 0); - Dprintk("setting P4_IQ_COUNTER2 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000)); - wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1); - apic_write(APIC_LVTPC, APIC_DM_NMI); - wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1, 0); - } - else - { - return 0; - } + wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0); + wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0); + Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000)); + wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1); + apic_write(APIC_LVTPC, APIC_DM_NMI); + wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); return 1; } void __pminit setup_apic_nmi_watchdog(void) { + int cpu = smp_processor_id(); + if (!nmi_watchdog) return; @@ -250,6 +237,10 @@ default: return; } + + init_ac_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); + nmi_timer_fn(NULL); + nmi_pm_init(); } @@ -280,11 +271,11 @@ spin_unlock_irqrestore(&watchdog_lock, flags); } -void nmi_watchdog_tick (struct cpu_user_regs * regs) +void nmi_watchdog_tick(struct cpu_user_regs * regs) { int sum, cpu = smp_processor_id(); - sum = ac_timers[cpu].softirqs; + sum = nmi_timer_ticks[cpu]; if ( (last_irq_sums[cpu] == sum) && watchdog_on ) { @@ -310,22 +301,24 @@ { if ( nmi_perfctr_msr == MSR_P4_IQ_COUNTER0 ) { - if ( logical_proc_id[cpu] == 0 ) - { - wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0); - apic_write(APIC_LVTPC, APIC_DM_NMI); - wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1); - } - else - { - wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1, 0); - apic_write(APIC_LVTPC, APIC_DM_NMI); - wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1); - } + /* + * P4 quirks: + * - An overflown perfctr will assert its interrupt + * until the OVF flag in its CCCR is cleared. + * - LVTPC is masked on interrupt and must be + * unmasked by the LVTPC handler. + */ + wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); + apic_write(APIC_LVTPC, APIC_DM_NMI); } - else + else if ( nmi_perfctr_msr == MSR_P6_PERFCTR0 ) { - wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); + /* + * Only P6 based Pentium M need to re-unmask the apic vector but + * it doesn't hurt other P6 variants. + */ + apic_write(APIC_LVTPC, APIC_DM_NMI); } + wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); } } diff -Nru a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c 2005-05-26 13:03:55 -04:00 +++ b/xen/arch/x86/setup.c 2005-05-26 13:03:55 -04:00 @@ -100,8 +100,6 @@ int acpi_disabled; -int logical_proc_id[NR_CPUS]; - int acpi_force; char acpi_param[10] = ""; static void parse_acpi_param(char *s) @@ -196,6 +194,8 @@ trap_init(); + ac_timer_init(); + time_init(); arch_init_memory(); @@ -214,8 +214,6 @@ initialize_keytable(); serial_init_stage2(); - - ac_timer_init(); init_xen_time(); diff -Nru a/xen/common/ac_timer.c b/xen/common/ac_timer.c --- a/xen/common/ac_timer.c 2005-05-26 13:03:55 -04:00 +++ b/xen/common/ac_timer.c 2005-05-26 13:03:55 -04:00 @@ -26,8 +26,16 @@ */ #define TIMER_SLOP (50*1000) /* ns */ +struct ac_timers { + spinlock_t lock; + struct ac_timer **heap; + unsigned int softirqs; +} __cacheline_aligned; + struct ac_timers ac_timers[NR_CPUS]; +extern int reprogram_ac_timer(s_time_t timeout); + /**************************************************************************** * HEAP OPERATIONS. _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |