aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xensource.com>2007-10-17 15:37:36 +0100
committerKeir Fraser <keir@xensource.com>2007-10-17 15:37:36 +0100
commiteb5916fb1fedde781742c924b6a13e482e92fca0 (patch)
treef60c85146ec3b0f06dcf8ac78940c1d85a7a9fab
parent0ae9ef55acbc7dce43153b059ac6fbdee2268ffe (diff)
downloadxen-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.c1
-rw-r--r--xen/arch/x86/smpboot.c2
-rw-r--r--xen/arch/x86/traps.c45
-rw-r--r--xen/arch/x86/x86_32/traps.c10
-rw-r--r--xen/arch/x86/x86_64/traps.c10
-rw-r--r--xen/include/asm-x86/msr.h13
-rw-r--r--xen/include/asm-x86/system.h4
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 *)&regs->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