WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Clean up NMI watchdog handler. No need to hack into ac_t

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Clean up NMI watchdog handler. No need to hack into ac_timer structs.
From: BitKeeper Bot <riel@xxxxxxxxxxx>
Date: Thu, 26 May 2005 16:09:52 +0000
Delivery-date: Thu, 26 May 2005 17:03:09 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: Xen Development List <xen-devel@xxxxxxxxxxxxxxxxxxx>
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Clean up NMI watchdog handler. No need to hack into ac_timer structs., BitKeeper Bot <=