[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Fix up the way we initialise and set the NMI heartbeat



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 026e5ef0aa3c8e1af5d70ab01ca4cbeb9c72a64d
# Parent  903420e4d449433c30d9b623847b29b0c2c765bc
Fix up the way we initialise and set the NMI heartbeat
timers. Also, compund updates to APIC ICR and ICR2 registers
must be done with interrupts disabled to ensure local
atomicity.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 903420e4d449 -r 026e5ef0aa3c xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Fri Jan 13 14:59:40 2006
+++ b/xen/arch/x86/apic.c       Fri Jan 13 15:09:45 2006
@@ -451,7 +451,8 @@
             printk("No ESR for 82489DX.\n");
     }
 
-    setup_apic_nmi_watchdog();
+    if (nmi_watchdog == NMI_LOCAL_APIC)
+        setup_apic_nmi_watchdog();
 }
 
 /*
diff -r 903420e4d449 -r 026e5ef0aa3c xen/arch/x86/nmi.c
--- a/xen/arch/x86/nmi.c        Fri Jan 13 14:59:40 2006
+++ b/xen/arch/x86/nmi.c        Fri Jan 13 15:09:45 2006
@@ -33,10 +33,6 @@
 #include <asm/apic.h>
 
 unsigned int nmi_watchdog = NMI_NONE;
-static spinlock_t   watchdog_lock = SPIN_LOCK_UNLOCKED;
-static unsigned int watchdog_disable_count = 1;
-static unsigned int watchdog_on;
-
 static unsigned int nmi_hz = HZ;
 static unsigned int nmi_perfctr_msr;   /* the MSR to reset in NMI handler */
 static unsigned int nmi_p4_cccr_val;
@@ -314,18 +310,8 @@
 
 void __pminit setup_apic_nmi_watchdog(void)
 {
-    int cpu = smp_processor_id();
-
-    if ( nmi_active < 0 )
-       return;
-
-    if ( !nmi_watchdog )
-    {
-       /* Force the watchdog to always be disabled. */
-       watchdog_disable_count++;
-       nmi_active = -1;
-       return;
-    }
+    if (!nmi_watchdog)
+        return;
 
     switch (boot_cpu_data.x86_vendor) {
     case X86_VENDOR_AMD:
@@ -358,45 +344,37 @@
 
     lapic_nmi_owner = LAPIC_NMI_WATCHDOG;
     nmi_active = 1;
-
-    init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu);
 }
 
 static unsigned int
 last_irq_sums [NR_CPUS],
     alert_counter [NR_CPUS];
 
+static atomic_t watchdog_disable_count = ATOMIC_INIT(1);
+
 void watchdog_disable(void)
 {
-    unsigned long flags;
-
-    spin_lock_irqsave(&watchdog_lock, flags);
-
-    if ( watchdog_disable_count++ == 0 )
-        watchdog_on = 0;
-
-    spin_unlock_irqrestore(&watchdog_lock, flags);
+    atomic_inc(&watchdog_disable_count);
 }
 
 void watchdog_enable(void)
 {
-    unsigned int  cpu;
-    unsigned long flags;
-
-    spin_lock_irqsave(&watchdog_lock, flags);
-
-    if ( --watchdog_disable_count == 0 )
+    static unsigned long heartbeat_initialised;
+    unsigned int cpu;
+
+    if ( !atomic_dec_and_test(&watchdog_disable_count) ||
+         test_and_set_bit(0, &heartbeat_initialised) )
+        return;
+
+    /*
+     * Activate periodic heartbeats. We cannot do this earlier during 
+     * setup because the timer infrastructure is not available.
+     */
+    for_each_online_cpu ( cpu )
     {
-        watchdog_on = 1;
-        /*
-         * Ensure periodic heartbeats are active. We cannot do this earlier
-         * during setup because the timer infrastructure is not available. 
-         */
-        for_each_online_cpu ( cpu )
-            set_timer(&nmi_timer[cpu], NOW());
-    }
-
-    spin_unlock_irqrestore(&watchdog_lock, flags);
+        init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu);
+        set_timer(&nmi_timer[cpu], NOW());
+    }
 }
 
 void nmi_watchdog_tick(struct cpu_user_regs * regs)
@@ -405,7 +383,7 @@
 
     sum = nmi_timer_ticks[cpu];
 
-    if ( (last_irq_sums[cpu] == sum) && watchdog_on )
+    if ( (last_irq_sums[cpu] == sum) && !atomic_read(&watchdog_disable_count) )
     {
         /*
          * Ayiee, looks like this CPU is stuck ... wait a few IRQs (5 seconds) 
@@ -457,14 +435,17 @@
  * 8-3 and 8-4 in IA32 Reference Manual Volume 3. We send the IPI to
  * our own APIC ID explicitly which is valid.
  */
-static void do_nmi_trigger(unsigned char key) {
+static void do_nmi_trigger(unsigned char key)
+{
     u32 id = apic_read(APIC_ID);
 
-    printk("triggering NMI on APIC ID %x\n", id);
-
+    printk("Triggering NMI on APIC ID %x\n", id);
+
+    local_irq_disable();
     apic_wait_icr_idle();
     apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id));
     apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_INT_ASSERT);
+    local_irq_enable();
 }
 
 static __init int register_nmi_trigger(void)
diff -r 903420e4d449 -r 026e5ef0aa3c xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Jan 13 14:59:40 2006
+++ b/xen/arch/x86/setup.c      Fri Jan 13 15:09:45 2006
@@ -478,7 +478,8 @@
 
     schedulers_start();
 
-    watchdog_enable();
+    if ( opt_watchdog ) 
+        watchdog_enable();
 
     shadow_mode_init();
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.