ia64/xen-unstable

changeset 8593:903420e4d449

Debug keyhandlers for triggering an NMI and examine current NMI state.

Add 'N' keyhandler to dump the current per CPU NMI counts and the
current NMI mask/pending status.

Add 'n' keyhandler to trigger an NMI by sending an IPI. For some
reason the destination shorthand for self is not valid when used with
the NMI delivery mode so we send the IPI to our own APIC ID
explicitly.

Signed-off-by: Ian Campbell <Ian.Campbell@XenSource.com>
author Ian.Campbell@xensource.com
date Fri Jan 13 14:59:40 2006 +0000 (2006-01-13)
parents e888f9b28a5b
children 026e5ef0aa3c
files xen/arch/x86/nmi.c xen/common/keyhandler.c
line diff
     1.1 --- a/xen/arch/x86/nmi.c	Fri Jan 13 15:22:36 2006 +0100
     1.2 +++ b/xen/arch/x86/nmi.c	Fri Jan 13 14:59:40 2006 +0000
     1.3 @@ -23,12 +23,14 @@
     1.4  #include <xen/sched.h>
     1.5  #include <xen/console.h>
     1.6  #include <xen/smp.h>
     1.7 +#include <xen/keyhandler.h>
     1.8  #include <asm/current.h>
     1.9  #include <asm/mc146818rtc.h>
    1.10  #include <asm/msr.h>
    1.11  #include <asm/mpspec.h>
    1.12  #include <asm/debugger.h>
    1.13  #include <asm/div64.h>
    1.14 +#include <asm/apic.h>
    1.15  
    1.16  unsigned int nmi_watchdog = NMI_NONE;
    1.17  static spinlock_t   watchdog_lock = SPIN_LOCK_UNLOCKED;
    1.18 @@ -448,3 +450,26 @@ void nmi_watchdog_tick(struct cpu_user_r
    1.19          write_watchdog_counter(NULL);
    1.20      }
    1.21  }
    1.22 +
    1.23 +/*
    1.24 + * For some reason the destination shorthand for self is not valid
    1.25 + * when used with the NMI delivery mode. This is documented in Tables
    1.26 + * 8-3 and 8-4 in IA32 Reference Manual Volume 3. We send the IPI to
    1.27 + * our own APIC ID explicitly which is valid.
    1.28 + */
    1.29 +static void do_nmi_trigger(unsigned char key) {
    1.30 +    u32 id = apic_read(APIC_ID);
    1.31 +
    1.32 +    printk("triggering NMI on APIC ID %x\n", id);
    1.33 +
    1.34 +    apic_wait_icr_idle();
    1.35 +    apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id));
    1.36 +    apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_INT_ASSERT);
    1.37 +}
    1.38 +
    1.39 +static __init int register_nmi_trigger(void)
    1.40 +{
    1.41 +    register_keyhandler('n', do_nmi_trigger, "trigger an NMI");
    1.42 +    return 0;
    1.43 +}
    1.44 +__initcall(register_nmi_trigger);
     2.1 --- a/xen/common/keyhandler.c	Fri Jan 13 15:22:36 2006 +0100
     2.2 +++ b/xen/common/keyhandler.c	Fri Jan 13 14:59:40 2006 +0000
     2.3 @@ -185,6 +185,27 @@ void do_debug_key(unsigned char key, str
     2.4                               bit. */
     2.5  }
     2.6  
     2.7 +void do_nmi_stats(unsigned char key)
     2.8 +{
     2.9 +    int i;
    2.10 +    struct domain *d;
    2.11 +    struct vcpu *v;
    2.12 +    printk("CPU\tNMI\n");
    2.13 +    for_each_cpu(i)
    2.14 +        printk("%3d\t%3d\n", i, nmi_count(i));
    2.15 +
    2.16 +    if ((d = dom0) == NULL)
    2.17 +        return;
    2.18 +    if ((v = d->vcpu[0]) == NULL)
    2.19 +        return;
    2.20 +    if (v->vcpu_flags & (VCPUF_nmi_pending|VCPUF_nmi_masked))
    2.21 +        printk("dom0 vpu0: NMI %s%s\n",
    2.22 +               v->vcpu_flags & VCPUF_nmi_pending ? "pending " : "",
    2.23 +               v->vcpu_flags & VCPUF_nmi_masked ? "masked " : "");
    2.24 +    else
    2.25 +        printk("dom0 vcpu0: NMI neither pending nor masked\n");
    2.26 +}
    2.27 +
    2.28  #ifndef NDEBUG
    2.29  void debugtrace_key(unsigned char key)
    2.30  {
    2.31 @@ -213,6 +234,7 @@ void initialize_keytable(void)
    2.32          'r', dump_runq,      "dump run queues");
    2.33      register_irq_keyhandler(
    2.34          'R', halt_machine,   "reboot machine"); 
    2.35 +    register_keyhandler('N', do_nmi_stats,   "NMI statistics");
    2.36  
    2.37  #ifndef NDEBUG
    2.38      register_keyhandler(