ia64/xen-unstable

changeset 17848:6b1795ee1b19

dom0 state dump

Since xenctx cannot (for obvious reasons) display the context of
dom0's vCPU-s, here are the beginnings of a console based mechanism to
achieve the same (useful if dom0 hangs with one or more de-scheduled
vCPU-s). The stack handling obviously needs improvement, but the
register context should come out fine in all cases.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 12 16:55:09 2008 +0100 (2008-06-12)
parents ec56331c056a
children 6f189de0f73d
files xen/arch/x86/traps.c xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/traps.c xen/common/keyhandler.c xen/include/asm-ia64/bug.h xen/include/asm-x86/domain.h
line diff
     1.1 --- a/xen/arch/x86/traps.c	Thu Jun 12 16:34:25 2008 +0100
     1.2 +++ b/xen/arch/x86/traps.c	Thu Jun 12 16:55:09 2008 +0100
     1.3 @@ -331,6 +331,28 @@ void show_execution_state(struct cpu_use
     1.4      show_stack(regs);
     1.5  }
     1.6  
     1.7 +void vcpu_show_execution_state(struct vcpu *v)
     1.8 +{
     1.9 +    printk("*** Dumping Dom%d vcpu#%d state: ***\n",
    1.10 +           v->domain->domain_id, v->vcpu_id);
    1.11 +
    1.12 +    if ( v == current )
    1.13 +    {
    1.14 +        show_execution_state(guest_cpu_user_regs());
    1.15 +        return;
    1.16 +    }
    1.17 +
    1.18 +    vcpu_pause(v); /* acceptably dangerous */
    1.19 +
    1.20 +    vcpu_show_registers(v);
    1.21 +    /* Todo: map arbitrary vcpu's top guest stack page here. */
    1.22 +    if ( (v->domain == current->domain) &&
    1.23 +         guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
    1.24 +        show_guest_stack(&v->arch.guest_context.user_regs);
    1.25 +
    1.26 +    vcpu_unpause(v);
    1.27 +}
    1.28 +
    1.29  char *trapstr(int trapnr)
    1.30  {
    1.31      static char *strings[] = { 
     2.1 --- a/xen/arch/x86/x86_32/traps.c	Thu Jun 12 16:34:25 2008 +0100
     2.2 +++ b/xen/arch/x86/x86_32/traps.c	Thu Jun 12 16:55:09 2008 +0100
     2.3 @@ -32,6 +32,26 @@ static void print_xen_info(void)
     2.4             arch, debug, print_tainted(taint_str));
     2.5  }
     2.6  
     2.7 +static void _show_registers(const struct cpu_user_regs *regs,
     2.8 +                            unsigned long crs[8], int guest_mode,
     2.9 +                            const char *context)
    2.10 +{
    2.11 +    printk("EIP:    %04x:[<%08x>]", regs->cs, regs->eip);
    2.12 +    if ( !guest_mode )
    2.13 +        print_symbol(" %s", regs->eip);
    2.14 +    printk("\nEFLAGS: %08x   CONTEXT: %s\n", regs->eflags, context);
    2.15 +    printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
    2.16 +           regs->eax, regs->ebx, regs->ecx, regs->edx);
    2.17 +    printk("esi: %08x   edi: %08x   ebp: %08x   esp: %08x\n",
    2.18 +           regs->esi, regs->edi, regs->ebp, regs->esp);
    2.19 +    printk("cr0: %08lx   cr4: %08lx   cr3: %08lx   cr2: %08lx\n",
    2.20 +           crs[0], crs[4], crs[3], crs[2]);
    2.21 +    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
    2.22 +           "ss: %04x   cs: %04x\n",
    2.23 +           regs->ds, regs->es, regs->fs,
    2.24 +           regs->gs, regs->ss, regs->cs);
    2.25 +}
    2.26 +
    2.27  void show_registers(struct cpu_user_regs *regs)
    2.28  {
    2.29      struct cpu_user_regs fault_regs = *regs;
    2.30 @@ -85,21 +105,8 @@ void show_registers(struct cpu_user_regs
    2.31      }
    2.32  
    2.33      print_xen_info();
    2.34 -    printk("CPU:    %d\nEIP:    %04x:[<%08x>]",
    2.35 -           smp_processor_id(), fault_regs.cs, fault_regs.eip);
    2.36 -    if ( !guest_mode(regs) )
    2.37 -        print_symbol(" %s", fault_regs.eip);
    2.38 -    printk("\nEFLAGS: %08x   CONTEXT: %s\n", fault_regs.eflags, context);
    2.39 -    printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
    2.40 -           fault_regs.eax, fault_regs.ebx, fault_regs.ecx, fault_regs.edx);
    2.41 -    printk("esi: %08x   edi: %08x   ebp: %08x   esp: %08x\n",
    2.42 -           fault_regs.esi, fault_regs.edi, fault_regs.ebp, fault_regs.esp);
    2.43 -    printk("cr0: %08lx   cr4: %08lx   cr3: %08lx   cr2: %08lx\n",
    2.44 -           fault_crs[0], fault_crs[4], fault_crs[3], fault_crs[2]);
    2.45 -    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
    2.46 -           "ss: %04x   cs: %04x\n",
    2.47 -           fault_regs.ds, fault_regs.es, fault_regs.fs,
    2.48 -           fault_regs.gs, fault_regs.ss, fault_regs.cs);
    2.49 +    printk("CPU:    %d\n", smp_processor_id());
    2.50 +    _show_registers(&fault_regs, fault_crs, guest_mode(regs), context);
    2.51  
    2.52      if ( this_cpu(ler_msr) && !guest_mode(regs) )
    2.53      {
    2.54 @@ -110,6 +117,22 @@ void show_registers(struct cpu_user_regs
    2.55      }
    2.56  }
    2.57  
    2.58 +void vcpu_show_registers(const struct vcpu *v)
    2.59 +{
    2.60 +    unsigned long crs[8];
    2.61 +
    2.62 +    /* No need to handle HVM for now. */
    2.63 +    if ( is_hvm_vcpu(v) )
    2.64 +        return;
    2.65 +
    2.66 +    crs[0] = v->arch.guest_context.ctrlreg[0];
    2.67 +    crs[2] = v->vcpu_info->arch.cr2;
    2.68 +    crs[3] = pagetable_get_paddr(v->arch.guest_table);
    2.69 +    crs[4] = v->arch.guest_context.ctrlreg[4];
    2.70 +
    2.71 +    _show_registers(&v->arch.guest_context.user_regs, crs, 1, "guest");
    2.72 +}
    2.73 +
    2.74  void show_page_walk(unsigned long addr)
    2.75  {
    2.76      unsigned long pfn, mfn, cr3 = read_cr3();
     3.1 --- a/xen/arch/x86/x86_64/traps.c	Thu Jun 12 16:34:25 2008 +0100
     3.2 +++ b/xen/arch/x86/x86_64/traps.c	Thu Jun 12 16:55:09 2008 +0100
     3.3 @@ -40,6 +40,33 @@ static void print_xen_info(void)
     3.4             debug, print_tainted(taint_str));
     3.5  }
     3.6  
     3.7 +static void _show_registers(const struct cpu_user_regs *regs,
     3.8 +                            unsigned long crs[8], int guest_mode,
     3.9 +                            const char *context)
    3.10 +{
    3.11 +    printk("RIP:    %04x:[<%016lx>]", regs->cs, regs->rip);
    3.12 +    if ( !guest_mode )
    3.13 +        print_symbol(" %s", regs->rip);
    3.14 +    printk("\nRFLAGS: %016lx   CONTEXT: %s\n", regs->rflags, context);
    3.15 +    printk("rax: %016lx   rbx: %016lx   rcx: %016lx\n",
    3.16 +           regs->rax, regs->rbx, regs->rcx);
    3.17 +    printk("rdx: %016lx   rsi: %016lx   rdi: %016lx\n",
    3.18 +           regs->rdx, regs->rsi, regs->rdi);
    3.19 +    printk("rbp: %016lx   rsp: %016lx   r8:  %016lx\n",
    3.20 +           regs->rbp, regs->rsp, regs->r8);
    3.21 +    printk("r9:  %016lx   r10: %016lx   r11: %016lx\n",
    3.22 +           regs->r9,  regs->r10, regs->r11);
    3.23 +    printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
    3.24 +           regs->r12, regs->r13, regs->r14);
    3.25 +    printk("r15: %016lx   cr0: %016lx   cr4: %016lx\n",
    3.26 +           regs->r15, crs[0], crs[4]);
    3.27 +    printk("cr3: %016lx   cr2: %016lx\n", crs[3], crs[2]);
    3.28 +    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
    3.29 +           "ss: %04x   cs: %04x\n",
    3.30 +           regs->ds, regs->es, regs->fs,
    3.31 +           regs->gs, regs->ss, regs->cs);
    3.32 +}
    3.33 +
    3.34  void show_registers(struct cpu_user_regs *regs)
    3.35  {
    3.36      struct cpu_user_regs fault_regs = *regs;
    3.37 @@ -91,28 +118,8 @@ void show_registers(struct cpu_user_regs
    3.38      }
    3.39  
    3.40      print_xen_info();
    3.41 -    printk("CPU:    %d\nRIP:    %04x:[<%016lx>]",
    3.42 -           smp_processor_id(), fault_regs.cs, fault_regs.rip);
    3.43 -    if ( !guest_mode(regs) )
    3.44 -        print_symbol(" %s", fault_regs.rip);
    3.45 -    printk("\nRFLAGS: %016lx   CONTEXT: %s\n", fault_regs.rflags, context);
    3.46 -    printk("rax: %016lx   rbx: %016lx   rcx: %016lx\n",
    3.47 -           fault_regs.rax, fault_regs.rbx, fault_regs.rcx);
    3.48 -    printk("rdx: %016lx   rsi: %016lx   rdi: %016lx\n",
    3.49 -           fault_regs.rdx, fault_regs.rsi, fault_regs.rdi);
    3.50 -    printk("rbp: %016lx   rsp: %016lx   r8:  %016lx\n",
    3.51 -           fault_regs.rbp, fault_regs.rsp, fault_regs.r8);
    3.52 -    printk("r9:  %016lx   r10: %016lx   r11: %016lx\n",
    3.53 -           fault_regs.r9,  fault_regs.r10, fault_regs.r11);
    3.54 -    printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
    3.55 -           fault_regs.r12, fault_regs.r13, fault_regs.r14);
    3.56 -    printk("r15: %016lx   cr0: %016lx   cr4: %016lx\n",
    3.57 -           fault_regs.r15, fault_crs[0], fault_crs[4]);
    3.58 -    printk("cr3: %016lx   cr2: %016lx\n", fault_crs[3], fault_crs[2]);
    3.59 -    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
    3.60 -           "ss: %04x   cs: %04x\n",
    3.61 -           fault_regs.ds, fault_regs.es, fault_regs.fs,
    3.62 -           fault_regs.gs, fault_regs.ss, fault_regs.cs);
    3.63 +    printk("CPU:    %d\n", smp_processor_id());
    3.64 +    _show_registers(&fault_regs, fault_crs, guest_mode(regs), context);
    3.65  
    3.66      if ( this_cpu(ler_msr) && !guest_mode(regs) )
    3.67      {
    3.68 @@ -123,6 +130,25 @@ void show_registers(struct cpu_user_regs
    3.69      }
    3.70  }
    3.71  
    3.72 +void vcpu_show_registers(const struct vcpu *v)
    3.73 +{
    3.74 +    const struct cpu_user_regs *regs = &v->arch.guest_context.user_regs;
    3.75 +    unsigned long crs[8];
    3.76 +
    3.77 +    /* No need to handle HVM for now. */
    3.78 +    if ( is_hvm_vcpu(v) )
    3.79 +        return;
    3.80 +
    3.81 +    crs[0] = v->arch.guest_context.ctrlreg[0];
    3.82 +    crs[2] = arch_get_cr2(v);
    3.83 +    crs[3] = pagetable_get_paddr(guest_kernel_mode(v, regs) ?
    3.84 +                                 v->arch.guest_table :
    3.85 +                                 v->arch.guest_table_user);
    3.86 +    crs[4] = v->arch.guest_context.ctrlreg[4];
    3.87 +
    3.88 +    _show_registers(regs, crs, 1, "guest");
    3.89 +}
    3.90 +
    3.91  void show_page_walk(unsigned long addr)
    3.92  {
    3.93      unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT;
     4.1 --- a/xen/common/keyhandler.c	Thu Jun 12 16:34:25 2008 +0100
     4.2 +++ b/xen/common/keyhandler.c	Thu Jun 12 16:55:09 2008 +0100
     4.3 @@ -127,6 +127,19 @@ static void dump_registers(unsigned char
     4.4      console_end_sync();
     4.5  }
     4.6  
     4.7 +static void dump_dom0_registers(unsigned char key)
     4.8 +{
     4.9 +    struct vcpu *v;
    4.10 +
    4.11 +    if ( dom0 == NULL )
    4.12 +        return;
    4.13 +
    4.14 +    printk("'%c' pressed -> dumping Dom0's registers\n", key);
    4.15 +
    4.16 +    for_each_vcpu ( dom0, v )
    4.17 +        vcpu_show_execution_state(v);
    4.18 +}
    4.19 +
    4.20  static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
    4.21  {
    4.22      printk("'%c' pressed -> rebooting machine\n", key);
    4.23 @@ -312,6 +325,9 @@ void __init initialize_keytable(void)
    4.24          'P', perfc_reset,    "reset performance counters");
    4.25  #endif
    4.26  
    4.27 +    register_keyhandler(
    4.28 +        '0', dump_dom0_registers, "dump Dom0 registers");
    4.29 +
    4.30      register_irq_keyhandler('%', do_debug_key,   "Trap to xendbg");
    4.31  }
    4.32  
     5.1 --- a/xen/include/asm-ia64/bug.h	Thu Jun 12 16:34:25 2008 +0100
     5.2 +++ b/xen/include/asm-ia64/bug.h	Thu Jun 12 16:55:09 2008 +0100
     5.3 @@ -4,6 +4,7 @@
     5.4  #define BUG() __bug(__FILE__, __LINE__)
     5.5  #define WARN() __warn(__FILE__, __LINE__)
     5.6  
     5.7 -#define dump_execution_state() printk("FIXME: implement ia64 dump_execution_state()\n");
     5.8 +#define dump_execution_state() printk("FIXME: implement ia64 dump_execution_state()\n")
     5.9 +#define vcpu_show_execution_state(v) printk("FIXME: implement ia64 vcpu_show_execution_state()\n")
    5.10  
    5.11  #endif /* __IA64_BUG_H__ */
     6.1 --- a/xen/include/asm-x86/domain.h	Thu Jun 12 16:34:25 2008 +0100
     6.2 +++ b/xen/include/asm-x86/domain.h	Thu Jun 12 16:55:09 2008 +0100
     6.3 @@ -351,6 +351,9 @@ struct arch_vcpu
     6.4  /* Continue the current hypercall via func(data) on specified cpu. */
     6.5  int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data);
     6.6  
     6.7 +void vcpu_show_execution_state(struct vcpu *);
     6.8 +void vcpu_show_registers(const struct vcpu *);
     6.9 +
    6.10  /* Clean up CR4 bits that are not under guest control. */
    6.11  unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4);
    6.12