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
|