[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 |