Dump last branch information on oopses Signed-off-by: Andi Kleen Index: linux/arch/x86_64/kernel/entry.S =================================================================== --- linux.orig/arch/x86_64/kernel/entry.S +++ linux/arch/x86_64/kernel/entry.S @@ -692,8 +692,38 @@ END(spurious_interrupt) /* * Exception entry points. */ + + .macro savemsr msr,var + movl $\msr,%ecx + rdmsr + movl %eax,\var + movl %edx,\var+4 + .endm + + .macro SAVELBR + cmpl $0,netburst + jz 1f + push %rax + push %rdx + push %rcx + savemsr 0x1da,lbr_tos + savemsr 0x1d7,ler_from + savemsr 0x1d8,ler_to + .set cnt,0 + .rept 16 + savemsr 0x680+cnt,lbr_from+cnt*8 + savemsr 0x6c0+cnt,lbr_to+cnt*8 + .set cnt,cnt+1 + .endr + pop %rcx + pop %rdx + pop %rax +1: + .endm + .macro zeroentry sym INTR_FRAME + SAVELBR pushq $0 /* push error code/oldrax */ CFI_ADJUST_CFA_OFFSET 8 pushq %rax /* push real oldrax to the rdi slot */ @@ -705,6 +735,7 @@ END(spurious_interrupt) .macro errorentry sym XCPT_FRAME + SAVELBR pushq %rax CFI_ADJUST_CFA_OFFSET 8 leaq \sym(%rip),%rax @@ -715,6 +746,7 @@ END(spurious_interrupt) /* error code is on the stack already */ /* handle NMI like exceptions that can happen everywhere */ .macro paranoidentry sym, ist=0, irqtrace=1 + SAVELBR SAVE_ALL cld movl $1,%ebx Index: linux/arch/x86_64/kernel/setup.c =================================================================== --- linux.orig/arch/x86_64/kernel/setup.c +++ linux/arch/x86_64/kernel/setup.c @@ -822,10 +822,13 @@ static void srat_detect_node(void) #endif } +int netburst; + static void __cpuinit init_intel(struct cpuinfo_x86 *c) { /* Cache sizes */ unsigned n; + unsigned long val; init_intel_cacheinfo(c); if (c->cpuid_level > 9 ) { @@ -867,6 +870,12 @@ static void __cpuinit init_intel(struct c->x86_max_cores = intel_num_cpu_cores(c); srat_detect_node(); + + if (c->x86 == 15) { + rdmsrl(MSR_IA32_DEBUGCTLMSR, val); + wrmsrl(MSR_IA32_DEBUGCTLMSR, val | 1); + netburst = 1; + } } static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) Index: linux/arch/x86_64/kernel/process.c =================================================================== --- linux.orig/arch/x86_64/kernel/process.c +++ linux/arch/x86_64/kernel/process.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -278,6 +279,9 @@ static int __init idle_setup (char *str) __setup("idle=", idle_setup); +unsigned long lbr_tos, lbr_from[16], lbr_to[16], ler_from, ler_to; +extern int netburst; + /* Prints also some state that isn't saved in the pt_regs */ void __show_regs(struct pt_regs * regs) { @@ -326,6 +330,18 @@ void __show_regs(struct pt_regs * regs) fs,fsindex,gs,gsindex,shadowgs); printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); + + if (netburst) { + unsigned i; + printk("LBR: TOS %lx", lbr_tos); + print_symbol(" LER_FROM %s", ler_from); + print_symbol(" LER_TO %s\n", ler_to); + for (i = 0; i < 16; i++) { + printk(" [%d]", i); + print_symbol(" FROM %s", lbr_from[i]); + print_symbol(" TO %s\n", lbr_from[i]); + } + } } void show_regs(struct pt_regs *regs)