Merge branch 'x86/pebs' into x86/unify-cpu-detect
Ingo Molnar [Wed, 10 Sep 2008 06:20:51 +0000 (08:20 +0200)]
Conflicts:
arch/x86/Kconfig.cpu
include/asm-x86/ds.h

Signed-off-by: Ingo Molnar <mingo@elte.hu>

1  2 
arch/x86/Kconfig.cpu
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
include/asm-x86/ds.h
include/asm-x86/processor.h
include/asm-x86/ptrace-abi.h
include/asm-x86/ptrace.h

@@@ -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.
Simple merge
Simple merge
Simple merge
Simple merge
   * 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 <markus.t.metzger@intel.com>, Dec 2007
+  * Copyright (C) 2007-2008 Intel Corporation.
+  * Markus Metzger <markus.t.metzger@intel.com>, 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 <linux/types.h>
  #include <linux/init.h>
  
- 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 */
Simple merge
@@@ -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 */
Simple merge