diff options
author | Keir Fraser <keir@xensource.com> | 2007-10-17 15:37:36 +0100 |
---|---|---|
committer | Keir Fraser <keir@xensource.com> | 2007-10-17 15:37:36 +0100 |
commit | eb5916fb1fedde781742c924b6a13e482e92fca0 (patch) | |
tree | f60c85146ec3b0f06dcf8ac78940c1d85a7a9fab | |
parent | 0ae9ef55acbc7dce43153b059ac6fbdee2268ffe (diff) | |
download | xen-eb5916fb1fedde781742c924b6a13e482e92fca0.tar.gz xen-eb5916fb1fedde781742c924b6a13e482e92fca0.tar.bz2 xen-eb5916fb1fedde781742c924b6a13e482e92fca0.zip |
x86: add option to display last exception records during register dumps
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r-- | xen/arch/x86/setup.c | 1 | ||||
-rw-r--r-- | xen/arch/x86/smpboot.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/traps.c | 45 | ||||
-rw-r--r-- | xen/arch/x86/x86_32/traps.c | 10 | ||||
-rw-r--r-- | xen/arch/x86/x86_64/traps.c | 10 | ||||
-rw-r--r-- | xen/include/asm-x86/msr.h | 13 | ||||
-rw-r--r-- | xen/include/asm-x86/system.h | 4 |
7 files changed, 78 insertions, 7 deletions
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index c2247918d9..a9c1beeba8 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -104,7 +104,6 @@ unsigned long xenheap_phys_start, xenheap_phys_end; extern void arch_init_memory(void); extern void init_IRQ(void); -extern void trap_init(void); extern void early_time_init(void); extern void early_cpu_init(void); extern void vesa_init(void); diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 9ffa664789..0ed832d511 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -492,8 +492,6 @@ void __devinit start_secondary(void *unused) */ unsigned int cpu = booting_cpu; - extern void percpu_traps_init(void); - set_processor_id(cpu); set_current(idle_vcpu[cpu]); this_cpu(curr_vcpu) = idle_vcpu[cpu]; diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 51d84739e9..6d085784e2 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -76,6 +76,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]; @@ -112,6 +114,9 @@ unsigned long do_get_debugreg(int reg); static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); +static int opt_ler; +boolean_param("ler", opt_ler); + #ifdef CONFIG_X86_32 #define stack_words_per_line 8 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp) @@ -2098,9 +2103,12 @@ asmlinkage int do_debug(struct cpu_user_regs *regs) /* 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; } @@ -2146,10 +2154,43 @@ void set_tss_desc(unsigned int n, void *addr) #endif } -void __init trap_init(void) +void __devinit percpu_traps_init(void) { - extern void percpu_traps_init(void); + subarch_percpu_traps_init(); + + if ( !opt_ler ) + return; + + 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 trap_init(void) +{ /* * Note that interrupt gates are always used, rather than trap gates. We * must have interrupts disabled until DS/ES/FS/GS are saved because the diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index bcbc14908c..3d77813e1b 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -104,6 +104,14 @@ void show_registers(struct cpu_user_regs *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) @@ -250,7 +258,7 @@ unsigned long do_iret(void) return 0; } -void __devinit percpu_traps_init(void) +void __devinit subarch_percpu_traps_init(void) { struct tss_struct *tss = &doublefault_tss; asmlinkage int hypercall(void); diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 992bf8d45c..79c7043146 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -112,6 +112,14 @@ void show_registers(struct cpu_user_regs *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) @@ -302,7 +310,7 @@ static int write_stack_trampoline( return 34; } -void __devinit percpu_traps_init(void) +void __devinit subarch_percpu_traps_init(void) { char *stack_bottom, *stack; int cpu = smp_processor_id(); diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h index 393bafa40a..79d37a33ad 100644 --- a/xen/include/asm-x86/msr.h +++ b/xen/include/asm-x86/msr.h @@ -105,6 +105,19 @@ static inline void write_efer(__u64 val) wrmsrl(MSR_EFER, val); } +DECLARE_PER_CPU(u32, ler_msr); + +static inline void ler_enable(void) +{ + u64 debugctl; + + if ( !this_cpu(ler_msr) ) + return; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); +} + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_MSR_H */ diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h index 2241795552..c464e1d454 100644 --- a/xen/include/asm-x86/system.h +++ b/xen/include/asm-x86/system.h @@ -314,4 +314,8 @@ static inline int local_irq_is_enabled(void) #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002 +void trap_init(void); +void percpu_traps_init(void); +void subarch_percpu_traps_init(void); + #endif |