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] Allow unknown NMIs to be propagated to domain0 via new

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Allow unknown NMIs to be propagated to domain0 via new
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 20 Dec 2005 18:12:08 +0000
Delivery-date: Tue, 20 Dec 2005 18:14:58 +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-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Allow unknown NMIs to be propagated to domain0 via new, Xen patchbot -unstable <=