Jan Beulich
2007-Aug-09 12:23 UTC
[Xen-devel] [PATCH] x86: add option to display last exception records during register dumps
A functionally similar patch will shortly be sent out for Linux. (Applies cleanly only on top of the previously sent SYSCALL/SYSENTER patch.) Signed-off-by: Jan Beulich <jbeulich@novell.com> Index: 2007-08-08/xen/arch/x86/traps.c ==================================================================--- 2007-08-08.orig/xen/arch/x86/traps.c 2007-08-08 11:40:02.000000000 +0200 +++ 2007-08-08/xen/arch/x86/traps.c 2007-08-08 11:57:04.000000000 +0200 @@ -75,6 +75,8 @@ char opt_nmi[10] = "fatal"; #endif string_param("nmi", opt_nmi); +DEFINE_PER_CPU(u32, ler_msr); + /* Master table, used by CPU0. */ idt_entry_t idt_table[IDT_ENTRIES]; @@ -2051,9 +2053,12 @@ asmlinkage int do_debug(struct cpu_user_ /* Save debug status register where guest OS can peek at it */ v->arch.guest_context.debugreg[6] = condition; + ler_enable(); + return do_guest_trap(TRAP_debug, regs, 0); out: + ler_enable(); return EXCRET_not_a_fault; } Index: 2007-08-08/xen/arch/x86/x86_32/traps.c ==================================================================--- 2007-08-08.orig/xen/arch/x86/x86_32/traps.c 2007-08-08 11:37:08.000000000 +0200 +++ 2007-08-08/xen/arch/x86/x86_32/traps.c 2007-08-08 11:57:04.000000000 +0200 @@ -18,6 +18,9 @@ #include <public/callback.h> +static int opt_ler; +boolean_param("ler", opt_ler); + static void print_xen_info(void) { char taint_str[TAINT_STRING_MAX_LEN]; @@ -87,6 +90,14 @@ void show_registers(struct cpu_user_regs "ss: %04x cs: %04x\n", fault_regs.ds, fault_regs.es, fault_regs.fs, fault_regs.gs, fault_regs.ss, fault_regs.cs); + if ( this_cpu(ler_msr) && !guest_mode(regs) ) + { + u32 from, to, hi; + + rdmsr(this_cpu(ler_msr), from, hi); + rdmsr(this_cpu(ler_msr) + 1, to, hi); + printk("ler: %08x -> %08x\n", from, to); + } } void show_page_walk(unsigned long addr) @@ -262,6 +273,32 @@ void __devinit percpu_traps_init(void) (unsigned long)tss, 235, 9); set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3); + + if ( opt_ler ) switch ( boot_cpu_data.x86_vendor ) + { + case X86_VENDOR_INTEL: + switch ( boot_cpu_data.x86 ) + { + case 6: + this_cpu(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + case 15: + this_cpu(ler_msr) = MSR_P4_LER_FROM_LIP; + break; + } + break; + case X86_VENDOR_AMD: + switch ( boot_cpu_data.x86 ) + { + case 6: + case 15: + case 16: + this_cpu(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + } + break; + } + ler_enable(); } void init_int80_direct_trap(struct vcpu *v) Index: 2007-08-08/xen/arch/x86/x86_64/traps.c ==================================================================--- 2007-08-08.orig/xen/arch/x86/x86_64/traps.c 2007-08-08 11:37:08.000000000 +0200 +++ 2007-08-08/xen/arch/x86/x86_64/traps.c 2007-08-08 11:57:04.000000000 +0200 @@ -26,6 +26,9 @@ asmlinkage void sysenter_entry(void); asmlinkage void compat_hypercall(void); asmlinkage void int80_direct_trap(void); +static int opt_ler; +boolean_param("ler", opt_ler); + static void print_xen_info(void) { char taint_str[TAINT_STRING_MAX_LEN]; @@ -96,6 +99,14 @@ void show_registers(struct cpu_user_regs "ss: %04x cs: %04x\n", fault_regs.ds, fault_regs.es, fault_regs.fs, fault_regs.gs, fault_regs.ss, fault_regs.cs); + if ( this_cpu(ler_msr) && !guest_mode(regs) ) + { + u64 from, to; + + rdmsrl(this_cpu(ler_msr), from); + rdmsrl(this_cpu(ler_msr) + 1, to); + printk("ler: %016lx -> %016lx\n", from, to); + } } void show_page_walk(unsigned long addr) @@ -336,12 +347,23 @@ void __devinit percpu_traps_init(void) wrmsrl(MSR_IA32_SYSENTER_ESP, (unsigned long)stack_bottom); wrmsrl(MSR_IA32_SYSENTER_EIP, (unsigned long)sysenter_entry); wrmsr(MSR_IA32_SYSENTER_CS, __HYPERVISOR_CS, 0); + if ( opt_ler ) switch ( boot_cpu_data.x86 ) + { + case 6: + this_cpu(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + case 15: + this_cpu(ler_msr) = MSR_P4_LER_FROM_LIP; + break; + } break; case X86_VENDOR_AMD: /* Trampoline for SYSCALL entry from compatibility mode. */ stack = (char *)L1_CACHE_ALIGN((unsigned long)stack); wrmsrl(MSR_CSTAR, (unsigned long)stack); stack += write_stack_trampoline(stack, stack_bottom, FLAT_USER_CS32); + if ( opt_ler && boot_cpu_data.x86 <= 16 ) + this_cpu(ler_msr) = MSR_IA32_LASTINTFROMIP; break; default: BUG(); @@ -350,6 +372,8 @@ void __devinit percpu_traps_init(void) /* Common SYSCALL parameters. */ wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS); wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); + + ler_enable(); } void init_int80_direct_trap(struct vcpu *v) Index: 2007-08-08/xen/include/asm-x86/msr.h ==================================================================--- 2007-08-08.orig/xen/include/asm-x86/msr.h 2007-08-08 11:45:33.000000000 +0200 +++ 2007-08-08/xen/include/asm-x86/msr.h 2007-08-08 11:57:04.000000000 +0200 @@ -225,6 +225,23 @@ static inline void write_efer(__u64 val) #define MSR_IA32_LASTINTFROMIP 0x1dd #define MSR_IA32_LASTINTTOIP 0x1de +#ifndef __ASSEMBLY__ + +DECLARE_PER_CPU(u32, ler_msr); + +static inline void ler_enable(void) +{ + if ( this_cpu(ler_msr) ) + { + u64 debugctl; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); + } +} + +#endif + #define MSR_IA32_MC0_CTL 0x400 #define MSR_IA32_MC0_STATUS 0x401 #define MSR_IA32_MC0_ADDR 0x402 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel