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

[Xen-devel] [PATCH 4 of 4 RFC] xen/nmi: DO NOT APPLY: debugkey to deliberatly invoke a reentrant NMI



FOR TESTING PURPOSES ONLY.  Use debug key '1'

diff -r f6ad86b61d5a -r 303d94fa720c xen/arch/x86/nmi.c
--- a/xen/arch/x86/nmi.c
+++ b/xen/arch/x86/nmi.c
@@ -39,6 +39,7 @@ static unsigned int nmi_perfctr_msr;  /* 
 static unsigned int nmi_p4_cccr_val;
 static DEFINE_PER_CPU(struct timer, nmi_timer);
 static DEFINE_PER_CPU(unsigned int, nmi_timer_ticks);
+static DEFINE_PER_CPU(unsigned int, reent_state);
 
 /* opt_watchdog: If true, run a watchdog NMI on each processor. */
 bool_t __initdata opt_watchdog = 0;
@@ -532,10 +533,106 @@ static struct keyhandler nmi_stats_keyha
     .desc = "NMI statistics"
 };
 
+void do_nmi_reent_fault(struct cpu_user_regs * regs)
+{
+    printk("In fault handler from NMI - iret from this is bad\n");
+    mdelay(10);
+}
+
+void do_nmi_reentrant_handler(void)
+{
+    volatile unsigned int * state_ptr = &(this_cpu(reent_state));
+    unsigned int state;
+
+    state = *state_ptr;
+
+    switch ( state )
+    {
+    case 0: // Not a reentrant NMI request
+        return;
+
+    case 1: // Outer NMI call - lets try to set up a reentrant case
+        printk("In outer reentrant case\n");
+
+        // Signal inner state
+        *state_ptr = state = 2;
+        // Queue up another NMI which cant currently be delivered
+        self_nmi();
+        /* printk("Queued up suplimentary NMI\n"); */
+        /* mdelay(10); */
+        /* // iret from exception handler should re-enable NMIs */
+        run_in_exception_handler(do_nmi_reent_fault);
+        /* mdelay(10); */
+
+        return;
+
+    case 2:
+        printk("In inner reentrant case - stuff will probably break 
quickly\n");
+        *state_ptr = state = 0;
+    }
+}
+
+static void nmi_reentrant(unsigned char key)
+{
+    volatile unsigned int * state_ptr = &(this_cpu(reent_state));
+    unsigned int state;
+    s_time_t deadline;
+
+    printk("*** Trying to force reentrant NMI ***\n");
+
+    if ( *state_ptr != 0 )
+    {
+        printk("State not ready - waiting for up to 2 seconds\n");
+        deadline = (NOW() + SECONDS(2));
+        do
+        {
+            cpu_relax();
+            state = *state_ptr;
+        } while ( NOW() < deadline && state != 0 );
+
+        if ( state != 0 )
+        {
+            printk("Forcibly resetting state\n");
+            *state_ptr = 0;
+        }
+        else
+            printk("Waiting seemed to work\n");
+    }
+
+    // Set up trap for NMI handler
+    *state_ptr = 1;
+    deadline = (NOW() + SECONDS(1));
+    printk("Set up trigger for NMI handler and waiting for magic\n");
+    self_nmi();
+
+    do
+    {
+        cpu_relax();
+        state = *state_ptr;
+    } while ( NOW() < deadline && state != 0 );
+
+    if ( state != 0 )
+    {
+        printk("Forcibly resetting state\n");
+        *state_ptr = 0;
+    }
+    else
+        printk("Apparently AOK\n");
+
+    printk("*** Done reentrant test ***\n");
+}
+
+static struct keyhandler nmi_reentrant_keyhandler = {
+    .diagnostic = 0,
+    .u.fn = nmi_reentrant,
+    .desc = "Reentrant NMI test"
+};
+
 static __init int register_nmi_trigger(void)
 {
     register_keyhandler('N', &nmi_trigger_keyhandler);
     register_keyhandler('n', &nmi_stats_keyhandler);
+    register_keyhandler('1', &nmi_reentrant_keyhandler);
     return 0;
 }
 __initcall(register_nmi_trigger);
diff -r f6ad86b61d5a -r 303d94fa720c xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -3183,6 +3183,7 @@ static int dummy_nmi_callback(struct cpu
  
 static nmi_callback_t nmi_callback = dummy_nmi_callback;
 
+extern void do_nmi_reentrant_handler(void);
 /* This function should never be called directly.  Use do_nmi() instead. */
 static void _do_nmi(struct cpu_user_regs *regs)
 {
@@ -3191,6 +3192,8 @@ static void _do_nmi(struct cpu_user_regs
 
     ++nmi_count(cpu);
 
+    do_nmi_reentrant_handler();
+
     if ( nmi_callback(regs, cpu) )
         return;
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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