Re: [PATCH] i386 add Intel PEBS and BTS cpufeature bits and detection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Friday 17 November 2006 23:57, Jeremy Fitzhardinge wrote:
> Andi Kleen wrote:
> > I have had private patches for that myself, using the MSRs on AMD
> > and Intel.
> >   
> 
> Would they be something that could be cleaned up into something
> mergeable?  

Hmm maybe.

> It would be nice to have something that could be left 
> enabled all the time, 

That would add considerable latency to all exceptions.

And unfortunately we take more than 16 jumps before
we figure out an oops, so all the previous data would be gone
if it was only done in the error path.

If the CPU had a "disable LBR on exceptions" bit that would
work. Unfortunately it hasn't.

> but an option would at least make the  
> functionality available.

If you have an debugging option you can as well enable the memory
based branch tracer, which gives a much larger picture
(but has somewhat more overhead too, i don't know how much
the difference is) Just someone would need to write a driver for it.
I think that would be more useful long term.

Here's the old MSR patch (for 64bit P4) for reference.  I had 
an AMD patch too, but I can't find it right now and on P4 
it works much better anyways because it has 16 LBRs instead of 4.

-Andi

Dump last branch information on oopses

Signed-off-by: Andi Kleen <[email protected]>

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 <linux/random.h>
 #include <linux/notifier.h>
 #include <linux/kprobes.h>
+#include <linux/kallsyms.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -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)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux