debuggers.hg
changeset 17880: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>
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