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

[Xen-changelog] Allow unknown NMIs to be propagated to domain0 via new



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 931acb64fbaf762fd47f9035b411ae6f1b5cb50b
# Parent  b34f4169b12ea40e4f60f1cb805d6bcadb0d08fc
Allow unknown NMIs to be propagated to domain0 via new
VIRQ_NMI. Also simplify x86_32 NMI handling -- there's
no need to greedily consume IO/parity errors in
assembly code as they can be deferred without causing
an interrupt storm (the NMI pin is always edge-triggered
even though the sources are level-asserted).

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

diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Tue Dec 20 11:55:19 2005
+++ b/xen/arch/x86/traps.c      Tue Dec 20 16:55:20 2005
@@ -1074,29 +1074,35 @@
     return 0;
 }
 
-unsigned long nmi_softirq_reason;
-static void nmi_softirq(void)
+
+/* Defer dom0 notification to softirq context (unsafe in NMI context). */
+static unsigned long nmi_dom0_softirq_reason;
+#define NMI_DOM0_PARITY_ERR 0
+#define NMI_DOM0_IO_ERR     1
+#define NMI_DOM0_UNKNOWN    2
+
+static void nmi_dom0_softirq(void)
 {
     if ( dom0 == NULL )
         return;
 
-    if ( test_and_clear_bit(0, &nmi_softirq_reason) )
+    if ( test_and_clear_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason) )
         send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR);
 
-    if ( test_and_clear_bit(1, &nmi_softirq_reason) )
+    if ( test_and_clear_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason) )
         send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR);
+
+    if ( test_and_clear_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason) )
+        send_guest_virq(dom0->vcpu[0], VIRQ_NMI);
 }
 
 asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
 {
-    /* Clear and disable the parity-error line. */
-    outb((inb(0x61)&15)|4,0x61);
-
     switch ( opt_nmi[0] )
     {
     case 'd': /* 'dom0' */
-        set_bit(0, &nmi_softirq_reason);
-        raise_softirq(NMI_SOFTIRQ);
+        set_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason);
+        raise_softirq(NMI_DOM0_SOFTIRQ);
     case 'i': /* 'ignore' */
         break;
     default:  /* 'fatal' */
@@ -1104,18 +1110,19 @@
         printk("\n\nNMI - MEMORY ERROR\n");
         fatal_trap(TRAP_nmi, regs);
     }
+
+    outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable parity check */
+    mdelay(1);
+    outb((inb(0x61) & 0x0b) | 0x00, 0x61); /* enable parity check */
 }
 
 asmlinkage void io_check_error(struct cpu_user_regs *regs)
 {
-    /* Clear and disable the I/O-error line. */
-    outb((inb(0x61)&15)|8,0x61);
-
     switch ( opt_nmi[0] )
     {
     case 'd': /* 'dom0' */
-        set_bit(0, &nmi_softirq_reason);
-        raise_softirq(NMI_SOFTIRQ);
+        set_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason);
+        raise_softirq(NMI_DOM0_SOFTIRQ);
     case 'i': /* 'ignore' */
         break;
     default:  /* 'fatal' */
@@ -1123,43 +1130,59 @@
         printk("\n\nNMI - I/O ERROR\n");
         fatal_trap(TRAP_nmi, regs);
     }
+
+    outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */
+    mdelay(1);
+    outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */
 }
 
 static void unknown_nmi_error(unsigned char reason)
 {
-    printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
-    printk("Dazed and confused, but trying to continue\n");
-    printk("Do you have a strange power saving mode enabled?\n");
-}
-
-static void default_do_nmi(struct cpu_user_regs *regs, unsigned long reason)
-{
-    if ( nmi_watchdog )
-        nmi_watchdog_tick(regs);
-
-    if ( reason & 0x80 )
-        mem_parity_error(regs);
-    else if ( reason & 0x40 )
-        io_check_error(regs);
-    else if ( !nmi_watchdog )
-        unknown_nmi_error((unsigned char)(reason&0xff));
+    switch ( opt_nmi[0] )
+    {
+    case 'd': /* 'dom0' */
+        set_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason);
+        raise_softirq(NMI_DOM0_SOFTIRQ);
+    case 'i': /* 'ignore' */
+        break;
+    default:  /* 'fatal' */
+        printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
+        printk("Dazed and confused, but trying to continue\n");
+        printk("Do you have a strange power saving mode enabled?\n");
+    }
 }
 
 static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
 {
-       return 0;
+    return 0;
 }
  
 static nmi_callback_t nmi_callback = dummy_nmi_callback;
  
-asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason)
+asmlinkage void do_nmi(struct cpu_user_regs *regs)
 {
     unsigned int cpu = smp_processor_id();
+    unsigned char reason;
 
     ++nmi_count(cpu);
 
-       if ( !nmi_callback(regs, cpu) )
-               default_do_nmi(regs, reason);
+    if ( nmi_callback(regs, cpu) )
+        return;
+
+    if ( nmi_watchdog )
+        nmi_watchdog_tick(regs);
+
+    /* Only the BSP gets external NMIs from the system. */
+    if ( cpu == 0 )
+    {
+        reason = inb(0x61);
+        if ( reason & 0x80 )
+            mem_parity_error(regs);
+        else if ( reason & 0x40 )
+            io_check_error(regs);
+        else if ( !nmi_watchdog )
+            unknown_nmi_error((unsigned char)(reason&0xff));
+    }
 }
 
 void set_nmi_callback(nmi_callback_t callback)
@@ -1169,7 +1192,7 @@
 
 void unset_nmi_callback(void)
 {
-       nmi_callback = dummy_nmi_callback;
+    nmi_callback = dummy_nmi_callback;
 }
 
 asmlinkage int math_state_restore(struct cpu_user_regs *regs)
@@ -1318,7 +1341,7 @@
 
     cpu_init();
 
-    open_softirq(NMI_SOFTIRQ, nmi_softirq);
+    open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq);
 }
 
 
diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Tue Dec 20 11:55:19 2005
+++ b/xen/arch/x86/vmx.c        Tue Dec 20 16:55:20 2005
@@ -335,7 +335,7 @@
 
 extern long evtchn_send(int lport);
 extern long do_block(void);
-void do_nmi(struct cpu_user_regs *, unsigned long);
+void do_nmi(struct cpu_user_regs *);
 
 static int check_vmx_controls(ctrls, msr)
 {
@@ -1850,7 +1850,7 @@
             break;
         }
         case TRAP_nmi:
-            do_nmi(&regs, 0);
+            do_nmi(&regs);
             break;
         default:
             vmx_reflect_exception(v);
diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Tue Dec 20 11:55:19 2005
+++ b/xen/arch/x86/x86_32/entry.S       Tue Dec 20 16:55:20 2005
@@ -601,15 +601,7 @@
        pushl %eax
        SAVE_ALL_NOSEGREGS(a)
 
-        # Check for hardware problems.
-        inb   $0x61,%al
-        testb $0x80,%al
-        jne   nmi_parity_err
-        testb $0x40,%al
-        jne   nmi_io_err
-        movl  %eax,%ebx
-        
-        # Okay, its almost a normal NMI tick. We can only process it if:
+        # We can only process the NMI if:
         #  A. We are the outermost Xen activation (in which case we have
         #     the selectors safely saved on our stack)
         #  B. DS and ES contain sane Xen values.
@@ -619,7 +611,7 @@
         movl  UREGS_eflags(%esp),%eax
         movb  UREGS_cs(%esp),%al
         testl $(3|X86_EFLAGS_VM),%eax
-        jnz   do_watchdog_tick
+        jnz   continue_nmi
         movl  %ds,%eax
         cmpw  $(__HYPERVISOR_DS),%ax
         jne   defer_nmi
@@ -627,15 +619,14 @@
         cmpw  $(__HYPERVISOR_DS),%ax
         jne   defer_nmi
 
-do_watchdog_tick:
+continue_nmi:
         movl  $(__HYPERVISOR_DS),%edx
         movl  %edx,%ds
         movl  %edx,%es
         movl  %esp,%edx
-        pushl %ebx   # reason
-        pushl %edx   # regs
+        pushl %edx
         call  do_nmi
-        addl  $8,%esp
+        addl  $4,%esp
         jmp   ret_from_intr
 
 defer_nmi:
@@ -648,55 +639,6 @@
         movl  $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_LOGICAL | \
                 TRAP_deferred_nmi),%ss:APIC_ICR(%eax)
         jmp   restore_all_xen
-
-nmi_parity_err:
-        # Clear and disable the parity-error line
-        andb $0xf,%al
-        orb  $0x4,%al
-        outb %al,$0x61
-        cmpb $'i',%ss:opt_nmi # nmi=ignore
-        je   nmi_out
-        bts  $0,%ss:nmi_softirq_reason
-        bts  $NMI_SOFTIRQ,%ss:irq_stat
-        cmpb $'d',%ss:opt_nmi # nmi=dom0
-        je   nmi_out
-        movl $(__HYPERVISOR_DS),%edx       # nmi=fatal
-        movl %edx,%ds
-        movl %edx,%es
-        movl %esp,%edx
-        push %edx
-        call mem_parity_error
-        addl $4,%esp
-nmi_out:movl  %ss:UREGS_eflags(%esp),%eax
-        movb  %ss:UREGS_cs(%esp),%al
-        testl $(3|X86_EFLAGS_VM),%eax
-        jz    restore_all_xen
-        movl  $(__HYPERVISOR_DS),%edx
-        movl  %edx,%ds
-        movl  %edx,%es
-        GET_CURRENT(%ebx)
-        jmp   test_all_events
-                
-nmi_io_err: 
-        # Clear and disable the I/O-error line
-        andb $0xf,%al
-        orb  $0x8,%al
-        outb %al,$0x61
-        cmpb $'i',%ss:opt_nmi # nmi=ignore
-        je   nmi_out
-        bts  $1,%ss:nmi_softirq_reason
-        bts  $NMI_SOFTIRQ,%ss:irq_stat
-        cmpb $'d',%ss:opt_nmi # nmi=dom0
-        je   nmi_out
-        movl $(__HYPERVISOR_DS),%edx       # nmi=fatal
-        movl %edx,%ds
-        movl %edx,%es
-        movl %esp,%edx
-        push %edx
-        call io_check_error                        
-        addl $4,%esp
-        jmp  nmi_out
-
 
 ENTRY(setup_vm86_frame)
         # Copies the entire stack frame forwards by 16 bytes.
diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Tue Dec 20 11:55:19 2005
+++ b/xen/arch/x86/x86_32/traps.c       Tue Dec 20 16:55:20 2005
@@ -160,9 +160,9 @@
 BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi)
 asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs)
 {
-    asmlinkage void do_nmi(struct cpu_user_regs *, unsigned long);
+    asmlinkage void do_nmi(struct cpu_user_regs *);
     ack_APIC_irq();
-    do_nmi(&regs, 0);
+    do_nmi(&regs);
 }
 
 void __init percpu_traps_init(void)
diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Tue Dec 20 11:55:19 2005
+++ b/xen/arch/x86/x86_64/entry.S       Tue Dec 20 16:55:20 2005
@@ -567,9 +567,7 @@
 ENTRY(nmi)
         pushq $0
         SAVE_ALL
-        inb   $0x61,%al
-        movl  %eax,%esi # reason
-        movq  %rsp,%rdi # regs
+        movq  %rsp,%rdi
         call  do_nmi
        jmp   restore_all_xen
 
diff -r b34f4169b12e -r 931acb64fbaf xen/include/public/xen.h
--- a/xen/include/public/xen.h  Tue Dec 20 11:55:19 2005
+++ b/xen/include/public/xen.h  Tue Dec 20 16:55:20 2005
@@ -67,12 +67,13 @@
  */
 #define VIRQ_TIMER      0  /* Timebase update, and/or requested timeout.  */
 #define VIRQ_DEBUG      1  /* Request guest to dump debug info.           */
-#define VIRQ_CONSOLE    2  /* (DOM0) bytes received on emergency console. */
+#define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
 #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
-#define VIRQ_PARITY_ERR 4  /* (DOM0) NMI parity error.                    */
-#define VIRQ_IO_ERR     5  /* (DOM0) NMI I/O error.                       */
+#define VIRQ_PARITY_ERR 4  /* (DOM0) NMI parity error (port 0x61, bit 7). */
+#define VIRQ_IO_ERR     5  /* (DOM0) NMI I/O error    (port 0x61, bit 6). */
 #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
-#define NR_VIRQS        7
+#define VIRQ_NMI        7  /* (DOM0) Unknown NMI (not from ISA port 0x61).*/
+#define NR_VIRQS        8
 
 /*
  * MMU-UPDATE REQUESTS
diff -r b34f4169b12e -r 931acb64fbaf xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Tue Dec 20 11:55:19 2005
+++ b/xen/include/xen/softirq.h Tue Dec 20 16:55:20 2005
@@ -6,7 +6,7 @@
 #define SCHEDULE_SOFTIRQ                  1
 #define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2
 #define KEYPRESS_SOFTIRQ                  3
-#define NMI_SOFTIRQ                       4
+#define NMI_DOM0_SOFTIRQ                  4
 #define PAGE_SCRUB_SOFTIRQ                5
 #define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ  6
 #define NR_SOFTIRQS                       7

_______________________________________________
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®.