dom0 state dump
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 12 Jun 2008 15:55:09 +0000 (16:55 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 12 Jun 2008 15:55:09 +0000 (16:55 +0100)
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>
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

index 9cb5ce612203904b54196b0423786f60feb1036d..218ede342a0dd422de7aff8d33f6fdc5f8f56c42 100644 (file)
@@ -331,6 +331,28 @@ void show_execution_state(struct cpu_user_regs *regs)
     show_stack(regs);
 }
 
+void vcpu_show_execution_state(struct vcpu *v)
+{
+    printk("*** Dumping Dom%d vcpu#%d state: ***\n",
+           v->domain->domain_id, v->vcpu_id);
+
+    if ( v == current )
+    {
+        show_execution_state(guest_cpu_user_regs());
+        return;
+    }
+
+    vcpu_pause(v); /* acceptably dangerous */
+
+    vcpu_show_registers(v);
+    /* Todo: map arbitrary vcpu's top guest stack page here. */
+    if ( (v->domain == current->domain) &&
+         guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
+        show_guest_stack(&v->arch.guest_context.user_regs);
+
+    vcpu_unpause(v);
+}
+
 char *trapstr(int trapnr)
 {
     static char *strings[] = { 
index 1913ccc291b57bb1de75c33e6dbcfa721b674c59..a09d15b523579183bcc438d55420843dc36709dc 100644 (file)
@@ -32,6 +32,26 @@ static void print_xen_info(void)
            arch, debug, print_tainted(taint_str));
 }
 
+static void _show_registers(const struct cpu_user_regs *regs,
+                            unsigned long crs[8], int guest_mode,
+                            const char *context)
+{
+    printk("EIP:    %04x:[<%08x>]", regs->cs, regs->eip);
+    if ( !guest_mode )
+        print_symbol(" %s", regs->eip);
+    printk("\nEFLAGS: %08x   CONTEXT: %s\n", regs->eflags, context);
+    printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
+           regs->eax, regs->ebx, regs->ecx, regs->edx);
+    printk("esi: %08x   edi: %08x   ebp: %08x   esp: %08x\n",
+           regs->esi, regs->edi, regs->ebp, regs->esp);
+    printk("cr0: %08lx   cr4: %08lx   cr3: %08lx   cr2: %08lx\n",
+           crs[0], crs[4], crs[3], crs[2]);
+    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
+           "ss: %04x   cs: %04x\n",
+           regs->ds, regs->es, regs->fs,
+           regs->gs, regs->ss, regs->cs);
+}
+
 void show_registers(struct cpu_user_regs *regs)
 {
     struct cpu_user_regs fault_regs = *regs;
@@ -85,21 +105,8 @@ void show_registers(struct cpu_user_regs *regs)
     }
 
     print_xen_info();
-    printk("CPU:    %d\nEIP:    %04x:[<%08x>]",
-           smp_processor_id(), fault_regs.cs, fault_regs.eip);
-    if ( !guest_mode(regs) )
-        print_symbol(" %s", fault_regs.eip);
-    printk("\nEFLAGS: %08x   CONTEXT: %s\n", fault_regs.eflags, context);
-    printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
-           fault_regs.eax, fault_regs.ebx, fault_regs.ecx, fault_regs.edx);
-    printk("esi: %08x   edi: %08x   ebp: %08x   esp: %08x\n",
-           fault_regs.esi, fault_regs.edi, fault_regs.ebp, fault_regs.esp);
-    printk("cr0: %08lx   cr4: %08lx   cr3: %08lx   cr2: %08lx\n",
-           fault_crs[0], fault_crs[4], fault_crs[3], fault_crs[2]);
-    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
-           "ss: %04x   cs: %04x\n",
-           fault_regs.ds, fault_regs.es, fault_regs.fs,
-           fault_regs.gs, fault_regs.ss, fault_regs.cs);
+    printk("CPU:    %d\n", smp_processor_id());
+    _show_registers(&fault_regs, fault_crs, guest_mode(regs), context);
 
     if ( this_cpu(ler_msr) && !guest_mode(regs) )
     {
@@ -110,6 +117,22 @@ void show_registers(struct cpu_user_regs *regs)
     }
 }
 
+void vcpu_show_registers(const struct vcpu *v)
+{
+    unsigned long crs[8];
+
+    /* No need to handle HVM for now. */
+    if ( is_hvm_vcpu(v) )
+        return;
+
+    crs[0] = v->arch.guest_context.ctrlreg[0];
+    crs[2] = v->vcpu_info->arch.cr2;
+    crs[3] = pagetable_get_paddr(v->arch.guest_table);
+    crs[4] = v->arch.guest_context.ctrlreg[4];
+
+    _show_registers(&v->arch.guest_context.user_regs, crs, 1, "guest");
+}
+
 void show_page_walk(unsigned long addr)
 {
     unsigned long pfn, mfn, cr3 = read_cr3();
index 71e8fbe2108b7c7c25a69d51e56145caee146e6e..14769786ec2a76579523c7949edfd60f3b6e267d 100644 (file)
@@ -40,6 +40,33 @@ static void print_xen_info(void)
            debug, print_tainted(taint_str));
 }
 
+static void _show_registers(const struct cpu_user_regs *regs,
+                            unsigned long crs[8], int guest_mode,
+                            const char *context)
+{
+    printk("RIP:    %04x:[<%016lx>]", regs->cs, regs->rip);
+    if ( !guest_mode )
+        print_symbol(" %s", regs->rip);
+    printk("\nRFLAGS: %016lx   CONTEXT: %s\n", regs->rflags, context);
+    printk("rax: %016lx   rbx: %016lx   rcx: %016lx\n",
+           regs->rax, regs->rbx, regs->rcx);
+    printk("rdx: %016lx   rsi: %016lx   rdi: %016lx\n",
+           regs->rdx, regs->rsi, regs->rdi);
+    printk("rbp: %016lx   rsp: %016lx   r8:  %016lx\n",
+           regs->rbp, regs->rsp, regs->r8);
+    printk("r9:  %016lx   r10: %016lx   r11: %016lx\n",
+           regs->r9,  regs->r10, regs->r11);
+    printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
+           regs->r12, regs->r13, regs->r14);
+    printk("r15: %016lx   cr0: %016lx   cr4: %016lx\n",
+           regs->r15, crs[0], crs[4]);
+    printk("cr3: %016lx   cr2: %016lx\n", crs[3], crs[2]);
+    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
+           "ss: %04x   cs: %04x\n",
+           regs->ds, regs->es, regs->fs,
+           regs->gs, regs->ss, regs->cs);
+}
+
 void show_registers(struct cpu_user_regs *regs)
 {
     struct cpu_user_regs fault_regs = *regs;
@@ -91,28 +118,8 @@ void show_registers(struct cpu_user_regs *regs)
     }
 
     print_xen_info();
-    printk("CPU:    %d\nRIP:    %04x:[<%016lx>]",
-           smp_processor_id(), fault_regs.cs, fault_regs.rip);
-    if ( !guest_mode(regs) )
-        print_symbol(" %s", fault_regs.rip);
-    printk("\nRFLAGS: %016lx   CONTEXT: %s\n", fault_regs.rflags, context);
-    printk("rax: %016lx   rbx: %016lx   rcx: %016lx\n",
-           fault_regs.rax, fault_regs.rbx, fault_regs.rcx);
-    printk("rdx: %016lx   rsi: %016lx   rdi: %016lx\n",
-           fault_regs.rdx, fault_regs.rsi, fault_regs.rdi);
-    printk("rbp: %016lx   rsp: %016lx   r8:  %016lx\n",
-           fault_regs.rbp, fault_regs.rsp, fault_regs.r8);
-    printk("r9:  %016lx   r10: %016lx   r11: %016lx\n",
-           fault_regs.r9,  fault_regs.r10, fault_regs.r11);
-    printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
-           fault_regs.r12, fault_regs.r13, fault_regs.r14);
-    printk("r15: %016lx   cr0: %016lx   cr4: %016lx\n",
-           fault_regs.r15, fault_crs[0], fault_crs[4]);
-    printk("cr3: %016lx   cr2: %016lx\n", fault_crs[3], fault_crs[2]);
-    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   "
-           "ss: %04x   cs: %04x\n",
-           fault_regs.ds, fault_regs.es, fault_regs.fs,
-           fault_regs.gs, fault_regs.ss, fault_regs.cs);
+    printk("CPU:    %d\n", smp_processor_id());
+    _show_registers(&fault_regs, fault_crs, guest_mode(regs), context);
 
     if ( this_cpu(ler_msr) && !guest_mode(regs) )
     {
@@ -123,6 +130,25 @@ void show_registers(struct cpu_user_regs *regs)
     }
 }
 
+void vcpu_show_registers(const struct vcpu *v)
+{
+    const struct cpu_user_regs *regs = &v->arch.guest_context.user_regs;
+    unsigned long crs[8];
+
+    /* No need to handle HVM for now. */
+    if ( is_hvm_vcpu(v) )
+        return;
+
+    crs[0] = v->arch.guest_context.ctrlreg[0];
+    crs[2] = arch_get_cr2(v);
+    crs[3] = pagetable_get_paddr(guest_kernel_mode(v, regs) ?
+                                 v->arch.guest_table :
+                                 v->arch.guest_table_user);
+    crs[4] = v->arch.guest_context.ctrlreg[4];
+
+    _show_registers(regs, crs, 1, "guest");
+}
+
 void show_page_walk(unsigned long addr)
 {
     unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT;
index 9194273322a81a6acf2d10b46a1bc078e5f5b774..2acd17ae7b9816b3e1da001397586d389077821f 100644 (file)
@@ -127,6 +127,19 @@ static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
     console_end_sync();
 }
 
+static void dump_dom0_registers(unsigned char key)
+{
+    struct vcpu *v;
+
+    if ( dom0 == NULL )
+        return;
+
+    printk("'%c' pressed -> dumping Dom0's registers\n", key);
+
+    for_each_vcpu ( dom0, v )
+        vcpu_show_execution_state(v);
+}
+
 static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
 {
     printk("'%c' pressed -> rebooting machine\n", key);
@@ -312,6 +325,9 @@ void __init initialize_keytable(void)
         'P', perfc_reset,    "reset performance counters");
 #endif
 
+    register_keyhandler(
+        '0', dump_dom0_registers, "dump Dom0 registers");
+
     register_irq_keyhandler('%', do_debug_key,   "Trap to xendbg");
 }
 
index 82f669c9a6f9c6afbf1862feda45227c36876cca..cf4b033c37babddf6198345af53e6b573dd34c0a 100644 (file)
@@ -4,6 +4,7 @@
 #define BUG() __bug(__FILE__, __LINE__)
 #define WARN() __warn(__FILE__, __LINE__)
 
-#define dump_execution_state() printk("FIXME: implement ia64 dump_execution_state()\n");
+#define dump_execution_state() printk("FIXME: implement ia64 dump_execution_state()\n")
+#define vcpu_show_execution_state(v) printk("FIXME: implement ia64 vcpu_show_execution_state()\n")
 
 #endif /* __IA64_BUG_H__ */
index 746e6e221ccaa928a2f1cfdb1824a8f41141b00d..1b42906982783a43255acf6e3df475c2f1f1906d 100644 (file)
@@ -351,6 +351,9 @@ struct arch_vcpu
 /* Continue the current hypercall via func(data) on specified cpu. */
 int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data);
 
+void vcpu_show_execution_state(struct vcpu *);
+void vcpu_show_registers(const struct vcpu *);
+
 /* Clean up CR4 bits that are not under guest control. */
 unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4);