[Xen-devel] [PATCH,RFC] dom0 state dump

Jan Beulich
2008-06-12T15:06:02Z

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>

Index: 2008-06-12/xen/arch/x86/traps.c
==================================================================---
2008-06-12.orig/xen/arch/x86/traps.c	2008-06-12 10:58:48.000000000 +0200
+++ 2008-06-12/xen/arch/x86/traps.c	2008-06-12 09:09:03.000000000 +0200
@@ -331,6 +331,15 @@ void show_execution_state(struct cpu_use
     show_stack(regs);
 }

+void vcpu_show_execution_state(struct vcpu *v)
+{
+    vcpu_show_registers(v);
+    /* XXX Should rather map the guest''s top 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);
+}
+
 char *trapstr(int trapnr)
 {
     static char *strings[] = {
Index: 2008-06-12/xen/arch/x86/x86_32/traps.c
==================================================================---
2008-06-12.orig/xen/arch/x86/x86_32/traps.c	2008-06-12 10:58:48.000000000 +0200
+++ 2008-06-12/xen/arch/x86/x86_32/traps.c	2008-06-12 09:09:03.000000000 +0200
@@ -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
     }

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

+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: 2008-06-12/xen/arch/x86/x86_64/traps.c
==================================================================---
2008-06-12.orig/xen/arch/x86/x86_64/traps.c	2008-06-12 10:58:48.000000000 +0200
+++ 2008-06-12/xen/arch/x86/x86_64/traps.c	2008-06-12 09:09:03.000000000 +0200
@@ -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
     }

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

+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: 2008-06-12/xen/common/keyhandler.c
==================================================================---
2008-06-12.orig/xen/common/keyhandler.c	2008-06-12 10:58:48.000000000 +0200
+++ 2008-06-12/xen/common/keyhandler.c	2008-06-12 11:00:00.000000000 +0200
@@ -130,6 +130,29 @@ static void dump_registers(unsigned char
     printk("\n");
 }

+static void dump_dom0_registers(unsigned char key)
+{
+    struct vcpu *v;
+
+    if ( !dom0 )
+        return;
+
+    printk("''%c'' pressed -> dumping Dom0''s
registers\n", key);
+
+    for_each_vcpu ( dom0, v )
+    {
+        printk("*** Dumping Dom0 vcpu#%d state: ***\n",
v->vcpu_id);
+        if ( v == current )
+            show_execution_state(guest_cpu_user_regs());
+        else
+        {
+            vcpu_pause(v);
+            vcpu_show_execution_state(v);
+            vcpu_unpause(v);
+        }
+    }
+}
+
 static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
 {
     printk("''%c'' pressed -> rebooting
machine\n", key);
@@ -315,6 +338,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: 2008-06-12/xen/include/asm-ia64/xenprocessor.h
==================================================================---
2008-06-12.orig/xen/include/asm-ia64/xenprocessor.h	2008-06-12
10:58:48.000000000 +0200
+++ 2008-06-12/xen/include/asm-ia64/xenprocessor.h	2008-06-12 09:09:03.000000000
+0200
@@ -250,6 +250,7 @@ typedef union {
 	};
 } ia64_pkr_t;

-#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 // _ASM_IA64_XENPROCESSOR_H
Index: 2008-06-12/xen/include/asm-x86/domain.h
==================================================================---
2008-06-12.orig/xen/include/asm-x86/domain.h	2008-06-12 10:58:48.000000000 +0200
+++ 2008-06-12/xen/include/asm-x86/domain.h	2008-06-12 09:09:03.000000000 +0200
@@ -352,6 +352,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);




_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com