Skip to contentSkip to conversation

x86, ptrace: support for branch trace store(BTS)

PATCH In review Siddha, Suresh B 3 participants 3 messages Nov 13, 2007 – Nov 15, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86, ptrace: support for branch trace store(BTS)

Support for Intel's last branch recording to ptrace. This gives debuggers access to this hardware feature and allows them to show an execution trace of the debugged application.

Last branch recording (see section 18.5 in the Intel 64 and IA-32 Architectures Software Developer's Manual) allows taking an execution trace of the running application without instrumentation. When a branch is executed, the hardware logs the source and destination address in a cyclic buffer given to it by the OS.

This can be a great debugging aid. It shows you how exactly you got where you currently are without requiring you to do lots of single stepping and rerunning.

This patch manages the various buffers, configures the trace hardware, disentangles the trace, and provides a user interface via ptrace. On the high-level design:
- there is one optional trace buffer per thread_struct
- upon a context switch, the trace hardware is reconfigured to either disable tracing or to use the appropriate buffer for the new task.
- tracing induces ~20% overhead as branch records are sent out on the bus.
- the hardware collects trace per processor. To disentangle the traces for different tasks, we use separate buffers and reconfigure the trace hardware.
- the internal buffer interpretation as well as the corresponding operations are selected at run-time by hardware detection
- different processors use different branch record formats

Opens:
- warnings due to code sharing between i386 and x86_64
- support for more processors (to come)
- ptrace command numbers (just picked some numbers randomly)

---

arch/x86/kernel/process_32.c +12 -0
Index: linux-2.6/arch/x86/kernel/process_32.c
===================================================================
@@ -735,6 +735,18 @@
 		__switch_to_xtra(prev_p, next_p, tss);
 
 	/*
+	 * Last branch recording recofiguration of trace hardware and
+	 * disentangling of trace data per task.
+	 */
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(prev_p)->flags & _TIF_BTS_TRACE_TS))
+		ptrace_bts_task_departs(prev_p);
+
+	if (unlikely(task_thread_info(next_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(next_p)->flags & _TIF_BTS_TRACE_TS))
+		ptrace_bts_task_arrives(next_p);
+
+	/*
 	 * Leave lazy mode, flushing any hypercalls made here.
 	 * This must be done before restoring TLS segments so
 	 * the GDT and LDT are properly updated, and must be
arch/x86/kernel/ptrace_32.c +33 -0
Index: linux-2.6/arch/x86/kernel/ptrace_32.c
===================================================================
@@ -24,6 +24,7 @@
 #include <asm/debugreg.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
+#include <asm/ptrace_bts.h>
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -274,6 +275,7 @@
 { 
 	clear_singlestep(child);
 	clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
+	ptrace_bts_task_detached(child);
 }
 
 /*
@@ -610,6 +612,37 @@
 					(struct user_desc __user *) data);
 		break;
 
+	case PTRACE_BTS_INIT:
+		ret = ptrace_bts_init();
+		break;
+
+	case PTRACE_BTS_ALLOCATE_BUFFER:
+		ret = ptrace_bts_allocate_bts(child, data);
+		break;
+
+	case PTRACE_BTS_GET_BUFFER_SIZE:
+		ret = ptrace_bts_get_buffer_size(child);
+		break;
+
+	case PTRACE_BTS_GET_INDEX:
+		ret = ptrace_bts_get_index(child);
+		break;
+
+	case PTRACE_BTS_READ_RECORD:
+		ret = ptrace_bts_read_record
+			(child, data,
+			 (struct ptrace_bts_record __user *) addr);
+		break;
+
+	case PTRACE_BTS_CONFIG:
+		ptrace_bts_config(child, data);
+		ret = 0;
+		break;
+
+	case PTRACE_BTS_STATUS:
+		ret = ptrace_bts_status(child);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
include/asm-x86/ptrace-abi.h +50 -0

54 lines not on this page · raw message

include/asm-x86/ptrace.h +35 -0
Index: linux-2.6/include/asm-x86/ptrace.h
===================================================================
@@ -4,8 +4,43 @@
 #include <linux/compiler.h>	/* For __user */
 #include <asm/ptrace-abi.h>
 
 #ifndef __ASSEMBLY__
 
+/* a branch trace record entry
+ *
+ * In order to unify the interface between various processor versions,
+ * we use the below data structure for all processors.
+ */
+enum ptrace_bts_qualifier {
+	PTRACE_BTS_INVALID = 0,
+	PTRACE_BTS_LBR,
+	PTRACE_BTS_TASK_ARRIVES,
+	PTRACE_BTS_TASK_DEPARTS
+};
+
+struct ptrace_bts_record {
+	enum ptrace_bts_qualifier qualifier;
+	union {
+		/* PTRACE_BTS_BRANCH */
+		struct {
+			void *from_ip;
+			void *to_ip;
+		} lbr;
+		/* PTRACE_BTS_TASK_ARRIVES or
+		   PTRACE_BTS_TASK_DEPARTS */
+		unsigned long long timestamp;
+	} variant;
+};
+
+#ifdef __KERNEL__
+
+struct task_struct;
+
+extern void ptrace_bts_task_arrives(struct task_struct *tsk);
+extern void ptrace_bts_task_departs(struct task_struct *tsk);
+
+#endif /* __KERNEL__ */
+
 #ifdef __i386__
 /* this struct defines the way the registers are stored on the
    stack during a system call. */
arch/x86/kernel/ptrace_bts.c new file +741 -0

741 lines not on this page · raw message

include/asm-x86/ptrace_bts.h new file +146 -0

146 lines not on this page · raw message

arch/x86/kernel/Makefile_32 +2 -1
Index: linux-2.6/arch/x86/kernel/Makefile_32
===================================================================
@@ -7,7 +7,8 @@
 obj-y	:= process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \
 		ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \
 		pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\
-		quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o
+		quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o\
+		ptrace_bts.o
 
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-y				+= cpu/
include/asm-x86/thread_info_32.h +5 -0
Index: linux-2.6/include/asm-x86/thread_info_32.h
===================================================================
@@ -137,6 +137,9 @@
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
 #define TIF_FREEZE		19	/* is freezing for suspend */
 #define TIF_NOTSC		20	/* TSC is not accessible in userland */
+/* gap to use same numbers for _32 and _64 variants */
+#define TIF_BTS_TRACE           24      /* record branches for this task */
+#define TIF_BTS_TRACE_TS        25      /* record scheduling event timestamps */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
@@ -151,6 +154,8 @@
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_NOTSC		(1<<TIF_NOTSC)
+#define _TIF_BTS_TRACE		(1<<TIF_BTS_TRACE)
+#define _TIF_BTS_TRACE_TS	(1<<TIF_BTS_TRACE_TS)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
include/asm-x86/processor_32.h +3 -0
Index: linux-2.6/include/asm-x86/processor_32.h
===================================================================
@@ -353,6 +353,9 @@
 	unsigned long	esp;
 	unsigned long	fs;
 	unsigned long	gs;
+/* Debug Store - if not 0 points to a DS Save Area configuration;
+ *               goes into MSR_IA32_DS_AREA */
+	unsigned long	ds_area;
 /* Hardware debugging registers */
 	unsigned long	debugreg[8];  /* %%db0-7 debug registers */
 /* fault info */
arch/x86/kernel/Makefile_64 +1 -1
Index: linux-2.6/arch/x86/kernel/Makefile_64
===================================================================
@@ -9,7 +9,7 @@
 		x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \
 		setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \
 		pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \
-		i8253.o
+		i8253.o ptrace_bts.o
 
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-y				+= cpu/
arch/x86/kernel/process_64.c +12 -0
Index: linux-2.6/arch/x86/kernel/process_64.c
===================================================================
@@ -677,6 +677,18 @@
 	    || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
 		__switch_to_xtra(prev_p, next_p, tss);
 
+	/*
+	 * Last branch recording recofiguration of trace hardware and
+	 * disentangling of trace data per task.
+	 */
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(prev_p)->flags & _TIF_BTS_TRACE_TS))
+		ptrace_bts_task_departs(prev_p);
+
+	if (unlikely(task_thread_info(next_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(next_p)->flags & _TIF_BTS_TRACE_TS))
+		ptrace_bts_task_arrives(next_p);
+
 	/* If the task has used fpu the last 5 timeslices, just do a full
 	 * restore of the math state immediately to avoid the trap; the
 	 * chances of needing FPU soon are obviously high now
arch/x86/kernel/ptrace_64.c +33 -0
Index: linux-2.6/arch/x86/kernel/ptrace_64.c
===================================================================
@@ -28,6 +28,7 @@
 #include <asm/desc.h>
 #include <asm/proto.h>
 #include <asm/ia32.h>
+#include <asm/ptrace_bts.h>
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -224,6 +225,7 @@
 void ptrace_disable(struct task_struct *child)
 { 
 	clear_singlestep(child);
+	ptrace_bts_task_detached(child);
 }
 
 static int putreg(struct task_struct *child,
@@ -555,6 +557,37 @@
 		break;
 	}
 
+	case PTRACE_BTS_INIT:
+		ret = ptrace_bts_init();
+		break;
+
+	case PTRACE_BTS_ALLOCATE_BUFFER:
+		ret = ptrace_bts_allocate_bts(child, data);
+		break;
+
+	case PTRACE_BTS_GET_BUFFER_SIZE:
+		ret = ptrace_bts_get_buffer_size(child);
+		break;
+
+	case PTRACE_BTS_GET_INDEX:
+		ret = ptrace_bts_get_index(child);
+		break;
+
+	case PTRACE_BTS_READ_RECORD:
+		ret = ptrace_bts_read_record
+			(child, data,
+			 (struct ptrace_bts_record __user *) addr);
+		break;
+
+	case PTRACE_BTS_CONFIG:
+		ptrace_bts_config(child, data);
+		ret = 0;
+		break;
+
+	case PTRACE_BTS_STATUS:
+		ret = ptrace_bts_status(child);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
include/asm-x86/processor_64.h +3 -0
Index: linux-2.6/include/asm-x86/processor_64.h
===================================================================
@@ -223,6 +223,9 @@
 	unsigned long	fs;
 	unsigned long	gs;
 	unsigned short	es, ds, fsindex, gsindex;	
+/* Debug Store - if not 0 points to a DS Save Area configuration;
+ *               goes into MSR_IA32_DS_AREA */
+	unsigned long	ds_area;
 /* Hardware debugging registers */
 	unsigned long	debugreg0;  
 	unsigned long	debugreg1;  
include/asm-x86/thread_info_64.h +4 -0
Index: linux-2.6/include/asm-x86/thread_info_64.h
===================================================================
@@ -123,6 +123,8 @@
 #define TIF_DEBUG		21	/* uses debug registers */
 #define TIF_IO_BITMAP		22	/* uses I/O bitmap */
 #define TIF_FREEZE		23	/* is freezing for suspend */
+#define TIF_BTS_TRACE		24	/* record branches for this task */
+#define TIF_BTS_TRACE_TS	25	/* record scheduling event timestamps */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
@@ -139,6 +141,8 @@
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
+#define _TIF_BTS_TRACE		(1<<TIF_BTS_TRACE)
+#define _TIF_BTS_TRACE_TS	(1<<TIF_BTS_TRACE_TS)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
#1 lore raw
Quoted 3 lines · Suresh B

Support for Intel's last branch recording to ptrace. This gives debuggers access to this hardware feature and allows them to show an execution trace of the debugged application.

Cool. Finally someone gets around to supporting this properly.

Ok mostly properly, the patch needs some improvements.

But can you please add a mode for tracing kernel code too? I guess this means a way to forbid it to user space or allocate the register. That would be probably needed by kernel debuggers too anyways, so might be better to add it from the begging.

I'm sure some people will suggest now that should be all only supported with utrace. My suggestion is to ignore them.

Also there was some discussion recently that complex kernel interfaces like this need manpages on proposal so that proper review of the interfaces is possible. I would suggest to write manpages (or manpages patches) and point to them on the next submission.

Quoted 9 lines

Index: linux-2.6/arch/x86/kernel/process_32.c
===================================================================

arch/x86/kernel/process_32.c +1 -0
@@ -735,6 +735,18 @@
 		__switch_to_xtra(prev_p, next_p, tss);
 
 	/*
+	 * Last branch recording recofiguration of trace hardware and

arch/x86/kernel/process_32.c line 748

Quoted 10 lines
arch/x86/kernel/process_32.c +10 -0
+	 * disentangling of trace data per task.
+	 */
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(prev_p)->flags & _TIF_BTS_TRACE_TS))
+		ptrace_bts_task_departs(prev_p);
+
+	if (unlikely(task_thread_info(next_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(next_p)->flags & _TIF_BTS_TRACE_TS))
+		ptrace_bts_task_arrives(next_p);
+

Congratulations. You managed to pick exactly the wrong place. Why do you think __switch_to_xtra was invented? The bits should be in CTXSW_PREV/NEXT and then the checks moved there. Then it would be zero cost for the nobody using it case.

Quoted 7 lines
arch/x86/kernel/process_32.c +7 -0
+#ifdef __i386__
+static int ptrace_bts_disable_netburst(void)
+{
+	unsigned long long debugctl_msr = 0;
+	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl_msr);
+	debugctl_msr &=
+		~((1 << 2) | /* TR */

arch/x86/kernel/process_32.c

Quoted 10 lines
arch/x86/kernel/process_32.c +10 -0
+		  (1 << 3));  /* BTS */
+	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl_msr);
+
+	return 0;
+}
+
+static int ptrace_bts_disable_pentium_m(void)
+{
+	unsigned long long debugctl_msr = 0;
+	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl_msr);

etc. Surely it would be faster to cache the value of the MSR in RAM? Might matter for the context switch.

arch/x86/kernel/process_32.c

Quoted 2 lines
arch/x86/kernel/process_32.c +2 -0
+	if (size_in_records > 4000)
+		return -EINVAL;

Nasty undocumented undefined magic numbers.

arch/x86/kernel/process_32.c

Quoted 7 lines
arch/x86/kernel/process_32.c +7 -0
+
+	if (!ptrace_bts_ops.allocate_bts)
+		return -EOPNOTSUPP;
+	return (*ptrace_bts_ops.allocate_bts)(child, size_in_records);
+}
+
+#ifdef __i386__

etc. The code duplication for i386 is indeed quite ugly. Would be good to find some better way to do this. A lot of it seems to be just different sizeof(), surely that could be passed around too or gotten from the ops structure?

Also it's unclear why you got different MSR access functions for 32bit and 64bit.

Quoted 1 line

+static int ptrace_bts_init_intel(void)

This should be probably in the standard CPU initialization code, possibly using synthesized feature bits too.

Also do you have user space to use this?

-Andi

#2 lore raw

Thanks for your comments.

Quoted 16 lines

-----Original Message-----
From: Andi Kleen [mailto:[email protected]]
Sent: Dienstag, 13. November 2007 21:21
To: Siddha, Suresh B
Cc: [email protected]; [email protected]; [email protected]; [email protected]; Metzger, Markus T; [email protected]
Subject: Re: [patch] x86, ptrace: support for branch trace store(BTS)

Quoted 1 line · Suresh B

Support for Intel's last branch recording to ptrace. This

gives debuggers

Quoted 1 line

access to this hardware feature and allows them to show an

execution trace

Quoted 1 line

of the debugged application.

Quoted 8 lines

Cool. Finally someone gets around to supporting this properly.

Ok mostly properly, the patch needs some improvements.

But can you please add a mode for tracing kernel code too? I guess this means a way to forbid it to user space or allocate the register. That would be probably needed by kernel debuggers too anyways, so might be better to add it from the begging.

That's a good point. The framework could be used for this. We would have to add a kernel API and disable user trace support. The kernel would probably want to collect trace per cpu, not per task.

That would be a separate feature that would best go into a different patch.

Quoted 7 lines

I'm sure some people will suggest now that should be all only supported with utrace. My suggestion is to ignore them.

Also there was some discussion recently that complex kernel interfaces like this need manpages on proposal so that proper review of the interfaces is possible. I would suggest to write manpages (or manpages patches) and point to them on the next submission.

Do you mean a patch to the "man ptrace" man page
that would elaborate on the comments I put into
include/asm-x86/ptrace-abi.h?

This would only be used for discussion in this mailing list, wouldn't it?

Quoted 21 lines
Quoted 3 lines

Index: linux-2.6/arch/x86/kernel/process_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/process_32.c

2007-11-07 09:08:32.%N +0100
Quoted 1 line

+++ linux-2.6/arch/x86/kernel/process_32.c 2007-11-07

09:09:36.%N +0100

arch/x86/kernel/process_32.c line 742

Quoted 9 lines
arch/x86/kernel/process_32.c +5 -0
@@ -735,6 +735,18 @@
 		__switch_to_xtra(prev_p, next_p, tss);
 
 	/*
+	 * Last branch recording recofiguration of trace hardware and
+	 * disentangling of trace data per task.
+	 */
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(prev_p)->flags & 

_TIF_BTS_TRACE_TS))

arch/x86/kernel/process_32.c

Quoted 4 lines
arch/x86/kernel/process_32.c +4 -0
+		ptrace_bts_task_departs(prev_p);
+
+	if (unlikely(task_thread_info(next_p)->flags & _TIF_BTS_TRACE ||
+		     task_thread_info(next_p)->flags & 

_TIF_BTS_TRACE_TS))

Quoted 7 lines

Review line 748

Quoted 2 lines
(quoted diff) +2 -0
+		ptrace_bts_task_arrives(next_p);
+

Congratulations. You managed to pick exactly the wrong place. Why do you think __switch_to_xtra was invented? The bits should be in CTXSW_PREV/NEXT and then the checks moved there. Then it would be zero cost for the nobody using it case.

I moved the code to __switch_to_xtra and set the
TIF_WORK_CTXSW_PREV/NEXT bits.
It looks better, now, thanks.

Quoted 12 lines
Quoted 12 lines
arch/x86/kernel/ptrace_bts.c new file +12 -0
+#ifdef __i386__
+static int ptrace_bts_disable_netburst(void)
+{
+	unsigned long long debugctl_msr = 0;
+	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl_msr);
+	debugctl_msr &=
+		~((1 << 2) | /* TR */
+		  (1 << 3));  /* BTS */
+	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl_msr);
+
+	return 0;
+}
Quoted 8 lines

arch/x86/kernel/ptrace_bts.c line 98

Quoted 5 lines
arch/x86/kernel/ptrace_bts.c new file +5 -0
+
+static int ptrace_bts_disable_pentium_m(void)
+{
+	unsigned long long debugctl_msr = 0;
+	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl_msr);

etc. Surely it would be faster to cache the value of the MSR in RAM? Might matter for the context switch.

If I cached the MSR value and only wrote it in the enable/disable routines,
I might implicitly undo somebody else's changes to other bits in that MSR.

Also, this code is not performance critical as it is executed only when switching to/from tasks that are being debugged.

Quoted 4 lines

arch/x86/kernel/ptrace_bts.c line 185

Quoted 2 lines
arch/x86/kernel/ptrace_bts.c new file +2 -0
+	if (size_in_records > 4000)
+		return -EINVAL;

Nasty undocumented undefined magic numbers.

I replaced it with a macro PTRACE_BTS_MAX_BTS_SIZE that is #defined at the beginning of that source file.

Quoted 4 lines
Quoted 4 lines
arch/x86/kernel/ptrace_bts.c new file +4 -0
+
+	if (!ptrace_bts_ops.allocate_bts)
+		return -EOPNOTSUPP;
+	return (*ptrace_bts_ops.allocate_bts)(child, size_in_records);
Quoted 8 lines

arch/x86/kernel/ptrace_bts.c line 32

Quoted 3 lines
arch/x86/kernel/ptrace_bts.c new file +3 -0
+}
+
+#ifdef __i386__

etc. The code duplication for i386 is indeed quite ugly. Would be good to find some better way to do this. A lot of it seems to be just different sizeof(), surely that could be passed around too or gotten from the ops structure?

The underlying problem is that the address size in the DS and the BTS depend on the processor mode as well as on the processor architecture. Netburst, for example, uses 32bit pointers in 32bit mode and 64bit pointers in 64bit mode.
Core2, on the other hand, uses 64bit pointers in both modes. While the processor mode is known statically, the processor architecture

is not.

I chose to model this using completely separate data structures and operations for each architecture variant to simplify adding support for new architectures.

For some of the operations, I could instead store a handful of parameters
in an architecture specific struct and use a common operation. For example,
I could store the size of the DS and BTS buffers, or the enable/disable bit-masks.

This would result in some kind of hybrid that I think is slightly harder

to understand and extend, but does not have a real benefit except for a marginal code size reduction.

How strongly do you think this needs to be changed?

I added the #ifdef __i386__ in order to get rid of some ugly type-cast warnings for cases that do not actually occur in practice.

For __i386__ I need to cast 32bit pointers into 64bit pointers and vice versa for architectures that use 64bit DS and BTS pointers in 32bit mode.
For __x86_64__ I never need to do that casting, so I chose to conditionally
compile that code.

Quoted 2 lines

Also it's unclear why you got different MSR access functions for 32bit and 64bit.

Actually, I got different MSR access functions for different processors,

because I need to touch different bits in that MSR. They just happen to collide with the 32bit/64bit distinction.

Quoted 4 lines
Quoted 1 line

+static int ptrace_bts_init_intel(void)

This should be probably in the standard CPU initialization code, possibly using synthesized feature bits too.

I will move the call to ptrace_bts_init_intel() into the intel setup code
and leave the function itself in ptrace_bts.c. This will obsolete the PTRACE_BTS_INIT command.

Quoted 1 line

Also do you have user space to use this?

The main target for this feature are application debuggers. We are currently
talking to gdb developers (internally) to have gdb make use of it.

thanks and regards,
markus.

Quoted 3 lines

-Andi

---------------------------------------------------------------------
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen Germany
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Douglas Lusk, Peter Gleissner, Hannes Schwaderer
Registergericht: Muenchen HRB 47456 Ust.-IdNr.
VAT Registration No.: DE129385895
Citibank Frankfurt (BLZ 502 109 00) 600119052

This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.