diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-06-12 16:55:09 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-06-12 16:55:09 +0100 |
commit | aadeb224555dd5c9292e316f7608c4b5daeb8835 (patch) | |
tree | a34951a180c84a51558d408cdc789539298afd47 | |
parent | a7bf85780578b98d71de4090efd30fbed0ed9291 (diff) | |
download | xen-aadeb224555dd5c9292e316f7608c4b5daeb8835.tar.gz xen-aadeb224555dd5c9292e316f7608c4b5daeb8835.tar.bz2 xen-aadeb224555dd5c9292e316f7608c4b5daeb8835.zip |
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>
-rw-r--r-- | xen/arch/x86/traps.c | 22 | ||||
-rw-r--r-- | xen/arch/x86/x86_32/traps.c | 53 | ||||
-rw-r--r-- | xen/arch/x86/x86_64/traps.c | 70 | ||||
-rw-r--r-- | xen/common/keyhandler.c | 16 | ||||
-rw-r--r-- | xen/include/asm-ia64/bug.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/domain.h | 3 |
6 files changed, 129 insertions, 38 deletions
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 9cb5ce6122..218ede342a 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -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[] = { diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 1913ccc291..a09d15b523 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -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(); diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 71e8fbe210..14769786ec 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -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; diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index 9194273322..2acd17ae7b 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -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"); } diff --git a/xen/include/asm-ia64/bug.h b/xen/include/asm-ia64/bug.h index 82f669c9a6..cf4b033c37 100644 --- a/xen/include/asm-ia64/bug.h +++ b/xen/include/asm-ia64/bug.h @@ -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 --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 746e6e221c..1b42906982 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -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); |