From: Ingo Molnar Date: Wed, 10 Sep 2008 06:20:51 +0000 (+0200) Subject: Merge branch 'x86/pebs' into x86/unify-cpu-detect X-Git-Tag: v2.6.28-rc1~711^2^2~13 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=81faaae45701484bd7368336e02f2a846153b22f;p=linux-2.6-omap-h63xx.git Merge branch 'x86/pebs' into x86/unify-cpu-detect Conflicts: arch/x86/Kconfig.cpu include/asm-x86/ds.h Signed-off-by: Ingo Molnar --- 81faaae45701484bd7368336e02f2a846153b22f diff --cc arch/x86/Kconfig.cpu index ab77d409fee,468ffc2df0e..1b29d6a8756 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@@ -416,64 -416,20 +416,82 @@@ config X86_DEBUGCTLMS def_bool y depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) +menuconfig PROCESSOR_SELECT + default y + bool "Supported processor vendors" if EMBEDDED + help + This lets you choose what x86 vendor support code your kernel + will include. + +config CPU_SUP_INTEL_32 + default y + bool "Support Intel processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Intel processors + +config CPU_SUP_INTEL_64 + default y + bool "Support Intel processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for Intel processors + +config CPU_SUP_CYRIX_32 + default y + bool "Support Cyrix processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Cyrix processors + +config CPU_SUP_AMD + default y + bool "Support AMD processors" if PROCESSOR_SELECT + help + This enables extended support for AMD processors + +config CPU_SUP_CENTAUR_32 + default y + bool "Support Centaur processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Centaur processors + +config CPU_SUP_CENTAUR_64 + default y + bool "Support Centaur processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for Centaur processors + +config CPU_SUP_TRANSMETA_32 + default y + bool "Support Transmeta processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Transmeta processors + +config CPU_SUP_UMC_32 + default y + bool "Support UMC processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for UMC processors ++ + config X86_DS + bool "Debug Store support" + default y + help + Add support for Debug Store. + This allows the kernel to provide a memory buffer to the hardware + to store various profiling and tracing events. + + config X86_PTRACE_BTS + bool "ptrace interface to Branch Trace Store" + default y + depends on (X86_DS && X86_DEBUGCTLMSR) + help + Add a ptrace interface to allow collecting an execution trace + of the traced task. + This collects control flow changes in a (cyclic) buffer and allows + debuggers to fill in the gaps and show an execution trace of the debuggee. diff --cc include/asm-x86/ds.h index 6b27c686fa1,72c5a190bf4..c3c953a45b2 --- a/include/asm-x86/ds.h +++ b/include/asm-x86/ds.h @@@ -2,71 -2,237 +2,237 @@@ * Debug Store (DS) support * * This provides a low-level interface to the hardware's Debug Store - * feature that is used for last branch recording (LBR) and + * feature that is used for branch trace store (BTS) and * precise-event based sampling (PEBS). * - * Different architectures use a different DS layout/pointer size. - * The below functions therefore work on a void*. + * It manages: + * - per-thread and per-cpu allocation of BTS and PEBS + * - buffer memory allocation (optional) + * - buffer overflow handling + * - buffer access * + * It assumes: + * - get_task_struct on all parameter tasks + * - current is allowed to trace parameter tasks * - * Since there is no user for PEBS, yet, only LBR (or branch - * trace store, BTS) is supported. * - * - * Copyright (C) 2007 Intel Corporation. - * Markus Metzger , Dec 2007 + * Copyright (C) 2007-2008 Intel Corporation. + * Markus Metzger , 2007-2008 */ -#ifndef _ASM_X86_DS_H -#define _ASM_X86_DS_H +#ifndef ASM_X86__DS_H +#define ASM_X86__DS_H + #ifdef CONFIG_X86_DS + #include #include - struct cpuinfo_x86; + struct task_struct; - /* a branch trace record entry + /* + * Request BTS or PEBS + * + * Due to alignement constraints, the actual buffer may be slightly + * smaller than the requested or provided buffer. * - * In order to unify the interface between various processor versions, - * we use the below data structure for all processors. + * Returns 0 on success; -Eerrno otherwise + * + * task: the task to request recording for; + * NULL for per-cpu recording on the current cpu + * base: the base pointer for the (non-pageable) buffer; + * NULL if buffer allocation requested + * size: the size of the requested or provided buffer + * ovfl: pointer to a function to be called on buffer overflow; + * NULL if cyclic buffer requested */ - enum bts_qualifier { - BTS_INVALID = 0, - BTS_BRANCH, - BTS_TASK_ARRIVES, - BTS_TASK_DEPARTS - }; + typedef void (*ds_ovfl_callback_t)(struct task_struct *); + extern int ds_request_bts(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl); + extern int ds_request_pebs(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl); + + /* + * Release BTS or PEBS resources + * + * Frees buffers allocated on ds_request. + * + * Returns 0 on success; -Eerrno otherwise + * + * task: the task to release resources for; + * NULL to release resources for the current cpu + */ + extern int ds_release_bts(struct task_struct *task); + extern int ds_release_pebs(struct task_struct *task); + + /* + * Return the (array) index of the write pointer. + * (assuming an array of BTS/PEBS records) + * + * Returns -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * pos (out): if not NULL, will hold the result + */ + extern int ds_get_bts_index(struct task_struct *task, size_t *pos); + extern int ds_get_pebs_index(struct task_struct *task, size_t *pos); + + /* + * Return the (array) index one record beyond the end of the array. + * (assuming an array of BTS/PEBS records) + * + * Returns -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * pos (out): if not NULL, will hold the result + */ + extern int ds_get_bts_end(struct task_struct *task, size_t *pos); + extern int ds_get_pebs_end(struct task_struct *task, size_t *pos); + + /* + * Provide a pointer to the BTS/PEBS record at parameter index. + * (assuming an array of BTS/PEBS records) + * + * The pointer points directly into the buffer. The user is + * responsible for copying the record. + * + * Returns the size of a single record on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * index: the index of the requested record + * record (out): pointer to the requested record + */ + extern int ds_access_bts(struct task_struct *task, + size_t index, const void **record); + extern int ds_access_pebs(struct task_struct *task, + size_t index, const void **record); + + /* + * Write one or more BTS/PEBS records at the write pointer index and + * advance the write pointer. + * + * If size is not a multiple of the record size, trailing bytes are + * zeroed out. + * + * May result in one or more overflow notifications. + * + * If called during overflow handling, that is, with index >= + * interrupt threshold, the write will wrap around. + * + * An overflow notification is given if and when the interrupt + * threshold is reached during or after the write. + * + * Returns the number of bytes written or -Eerrno. + * + * task: the task to access; + * NULL to access the current cpu + * buffer: the buffer to write + * size: the size of the buffer + */ + extern int ds_write_bts(struct task_struct *task, + const void *buffer, size_t size); + extern int ds_write_pebs(struct task_struct *task, + const void *buffer, size_t size); + + /* + * Same as ds_write_bts/pebs, but omit ownership checks. + * + * This is needed to have some other task than the owner of the + * BTS/PEBS buffer or the parameter task itself write into the + * respective buffer. + */ + extern int ds_unchecked_write_bts(struct task_struct *task, + const void *buffer, size_t size); + extern int ds_unchecked_write_pebs(struct task_struct *task, + const void *buffer, size_t size); + + /* + * Reset the write pointer of the BTS/PEBS buffer. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + */ + extern int ds_reset_bts(struct task_struct *task); + extern int ds_reset_pebs(struct task_struct *task); + + /* + * Clear the BTS/PEBS buffer and reset the write pointer. + * The entire buffer will be zeroed out. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + */ + extern int ds_clear_bts(struct task_struct *task); + extern int ds_clear_pebs(struct task_struct *task); + + /* + * Provide the PEBS counter reset value. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * value (out): the counter reset value + */ + extern int ds_get_pebs_reset(struct task_struct *task, u64 *value); + + /* + * Set the PEBS counter reset value. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * value: the new counter reset value + */ + extern int ds_set_pebs_reset(struct task_struct *task, u64 value); + + /* + * Initialization + */ + struct cpuinfo_x86; + extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); + + - struct bts_struct { - u64 qualifier; - union { - /* BTS_BRANCH */ - struct { - u64 from_ip; - u64 to_ip; - } lbr; - /* BTS_TASK_ARRIVES or - BTS_TASK_DEPARTS */ - u64 jiffies; - } variant; + /* + * The DS context - part of struct thread_struct. + */ + struct ds_context { + /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ + unsigned char *ds; + /* the owner of the BTS and PEBS configuration, respectively */ + struct task_struct *owner[2]; + /* buffer overflow notification function for BTS and PEBS */ + ds_ovfl_callback_t callback[2]; + /* the original buffer address */ + void *buffer[2]; + /* the number of allocated pages for on-request allocated buffers */ + unsigned int pages[2]; + /* use count */ + unsigned long count; + /* a pointer to the context location inside the thread_struct + * or the per_cpu context array */ + struct ds_context **this; + /* a pointer to the task owning this context, or NULL, if the + * context is owned by a cpu */ + struct task_struct *task; }; - /* Overflow handling mechanisms */ - #define DS_O_SIGNAL 1 /* send overflow signal */ - #define DS_O_WRAP 2 /* wrap around */ - - extern int ds_allocate(void **, size_t); - extern int ds_free(void **); - extern int ds_get_bts_size(void *); - extern int ds_get_bts_end(void *); - extern int ds_get_bts_index(void *); - extern int ds_set_overflow(void *, int); - extern int ds_get_overflow(void *); - extern int ds_clear(void *); - extern int ds_read_bts(void *, int, struct bts_struct *); - extern int ds_write_bts(void *, const struct bts_struct *); - extern unsigned long ds_debugctl_mask(void); - extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *c); + /* called by exit_thread() to free leftover contexts */ + extern void ds_free(struct ds_context *context); + + #else /* CONFIG_X86_DS */ + + #define ds_init_intel(config) do {} while (0) + #endif /* CONFIG_X86_DS */ -#endif /* _ASM_X86_DS_H */ +#endif /* ASM_X86__DS_H */ diff --cc include/asm-x86/ptrace-abi.h index d0cf3344a58,3397817eded..4298b8882a7 --- a/include/asm-x86/ptrace-abi.h +++ b/include/asm-x86/ptrace-abi.h @@@ -139,5 -140,6 +140,6 @@@ struct ptrace_bts_config BTS records are read from oldest to newest. Returns number of BTS records drained. */ + #endif /* CONFIG_X86_PTRACE_BTS */ -#endif +#endif /* ASM_X86__PTRACE_ABI_H */