# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1213286109 -3600
# Node ID 6b1795ee1b19d85183e0fd19f70b09340ba41e03
# Parent ec56331c056aea79b267ae5383a5ae09f4a37941
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@xxxxxxxxxx>
---
xen/arch/x86/traps.c | 22 +++++++++++++
xen/arch/x86/x86_32/traps.c | 53 +++++++++++++++++++++++---------
xen/arch/x86/x86_64/traps.c | 70 +++++++++++++++++++++++++++++--------------
xen/common/keyhandler.c | 16 +++++++++
xen/include/asm-ia64/bug.h | 3 +
xen/include/asm-x86/domain.h | 3 +
6 files changed, 129 insertions(+), 38 deletions(-)
diff -r ec56331c056a -r 6b1795ee1b19 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Thu Jun 12 16:34:25 2008 +0100
+++ b/xen/arch/x86/traps.c Thu Jun 12 16:55:09 2008 +0100
@@ -329,6 +329,28 @@ void show_execution_state(struct cpu_use
{
show_registers(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)
diff -r ec56331c056a -r 6b1795ee1b19 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c Thu Jun 12 16:34:25 2008 +0100
+++ b/xen/arch/x86/x86_32/traps.c Thu Jun 12 16:55:09 2008 +0100
@@ -30,6 +30,26 @@ static void print_xen_info(void)
printk("----[ Xen-%d.%d%s %s debug=%c %s ]----\n",
xen_major_version(), xen_minor_version(), xen_extra_version(),
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)
@@ -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) )
{
@@ -108,6 +115,22 @@ void show_registers(struct cpu_user_regs
rdmsr(this_cpu(ler_msr) + 1, to, hi);
printk("ler: %08x -> %08x\n", from, to);
}
+}
+
+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)
diff -r ec56331c056a -r 6b1795ee1b19 xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c Thu Jun 12 16:34:25 2008 +0100
+++ b/xen/arch/x86/x86_64/traps.c Thu Jun 12 16:55:09 2008 +0100
@@ -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) )
{
@@ -121,6 +128,25 @@ void show_registers(struct cpu_user_regs
rdmsrl(this_cpu(ler_msr) + 1, to);
printk("ler: %016lx -> %016lx\n", from, to);
}
+}
+
+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)
diff -r ec56331c056a -r 6b1795ee1b19 xen/common/keyhandler.c
--- a/xen/common/keyhandler.c Thu Jun 12 16:34:25 2008 +0100
+++ b/xen/common/keyhandler.c Thu Jun 12 16:55:09 2008 +0100
@@ -125,6 +125,19 @@ static void dump_registers(unsigned char
printk("\n");
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)
@@ -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");
}
diff -r ec56331c056a -r 6b1795ee1b19 xen/include/asm-ia64/bug.h
--- a/xen/include/asm-ia64/bug.h Thu Jun 12 16:34:25 2008 +0100
+++ b/xen/include/asm-ia64/bug.h Thu Jun 12 16:55:09 2008 +0100
@@ -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__ */
diff -r ec56331c056a -r 6b1795ee1b19 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h Thu Jun 12 16:34:25 2008 +0100
+++ b/xen/include/asm-x86/domain.h Thu Jun 12 16:55:09 2008 +0100
@@ -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);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|