|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |