Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ad5d703 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'tracing/hw-branch-tracing' into tracing/core



Merge reason: this topic is ready for upstream now. It passed
              Oleg's review and Andrew had no further mm/*
              objections/observations either.

Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parents 44347d94 1cb81b14
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -506,7 +506,6 @@ config X86_PTRACE_BTS
	bool "Branch Trace Store"
	default y
	depends on X86_DEBUGCTLMSR
	depends on BROKEN
	---help---
	  This adds a ptrace interface to the hardware's branch trace store.

+9 −0
Original line number Diff line number Diff line
@@ -167,6 +167,15 @@ config IOMMU_LEAK
	  Add a simple leak tracer to the IOMMU code. This is useful when you
	  are debugging a buggy device driver that leaks IOMMU mappings.

config X86_DS_SELFTEST
    bool "DS selftest"
    default y
    depends on DEBUG_KERNEL
    depends on X86_DS
	---help---
	  Perform Debug Store selftests at boot time.
	  If in doubt, say "N".

config HAVE_MMIOTRACE_SUPPORT
	def_bool y

+56 −26
Original line number Diff line number Diff line
@@ -15,8 +15,8 @@
 * - buffer allocation (memory accounting)
 *
 *
 * Copyright (C) 2007-2008 Intel Corporation.
 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008
 * Copyright (C) 2007-2009 Intel Corporation.
 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
 */

#ifndef _ASM_X86_DS_H
@@ -83,8 +83,10 @@ enum ds_feature {
 * The interrupt threshold is independent from the overflow callback
 * to allow users to use their own overflow interrupt handling mechanism.
 *
 * task: the task to request recording for;
 *       NULL for per-cpu recording on the current cpu
 * The function might sleep.
 *
 * task: the task to request recording for
 * cpu:  the cpu to request recording for
 * base: the base pointer for the (non-pageable) buffer;
 * size: the size of the provided buffer in bytes
 * ovfl: pointer to a function to be called on buffer overflow;
@@ -93,11 +95,18 @@ enum ds_feature {
 *     -1 if no interrupt threshold is requested.
 * flags: a bit-mask of the above flags
 */
extern struct bts_tracer *ds_request_bts(struct task_struct *task,
extern struct bts_tracer *ds_request_bts_task(struct task_struct *task,
					      void *base, size_t size,
					      bts_ovfl_callback_t ovfl,
					      size_t th, unsigned int flags);
extern struct pebs_tracer *ds_request_pebs(struct task_struct *task,
extern struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size,
					     bts_ovfl_callback_t ovfl,
					     size_t th, unsigned int flags);
extern struct pebs_tracer *ds_request_pebs_task(struct task_struct *task,
						void *base, size_t size,
						pebs_ovfl_callback_t ovfl,
						size_t th, unsigned int flags);
extern struct pebs_tracer *ds_request_pebs_cpu(int cpu,
					       void *base, size_t size,
					       pebs_ovfl_callback_t ovfl,
					       size_t th, unsigned int flags);
@@ -106,6 +115,8 @@ extern struct pebs_tracer *ds_request_pebs(struct task_struct *task,
 * Release BTS or PEBS resources
 * Suspend and resume BTS or PEBS tracing
 *
 * Must be called with irq's enabled.
 *
 * tracer: the tracer handle returned from ds_request_~()
 */
extern void ds_release_bts(struct bts_tracer *tracer);
@@ -115,6 +126,28 @@ extern void ds_release_pebs(struct pebs_tracer *tracer);
extern void ds_suspend_pebs(struct pebs_tracer *tracer);
extern void ds_resume_pebs(struct pebs_tracer *tracer);

/*
 * Release BTS or PEBS resources
 * Suspend and resume BTS or PEBS tracing
 *
 * Cpu tracers must call this on the traced cpu.
 * Task tracers must call ds_release_~_noirq() for themselves.
 *
 * May be called with irq's disabled.
 *
 * Returns 0 if successful;
 * -EPERM if the cpu tracer does not trace the current cpu.
 * -EPERM if the task tracer does not trace itself.
 *
 * tracer: the tracer handle returned from ds_request_~()
 */
extern int ds_release_bts_noirq(struct bts_tracer *tracer);
extern int ds_suspend_bts_noirq(struct bts_tracer *tracer);
extern int ds_resume_bts_noirq(struct bts_tracer *tracer);
extern int ds_release_pebs_noirq(struct pebs_tracer *tracer);
extern int ds_suspend_pebs_noirq(struct pebs_tracer *tracer);
extern int ds_resume_pebs_noirq(struct pebs_tracer *tracer);


/*
 * The raw DS buffer state as it is used for BTS and PEBS recording.
@@ -170,9 +203,9 @@ struct bts_struct {
		} lbr;
		/* BTS_TASK_ARRIVES or BTS_TASK_DEPARTS */
		struct {
			__u64 jiffies;
			__u64 clock;
			pid_t pid;
		} timestamp;
		} event;
	} variant;
};

@@ -201,8 +234,12 @@ struct bts_trace {
struct pebs_trace {
	struct ds_trace ds;

	/* the PEBS reset value */
	unsigned long long reset_value;
	/* the number of valid counters in the below array */
	unsigned int counters;

#define MAX_PEBS_COUNTERS 4
	/* the counter reset value */
	unsigned long long counter_reset[MAX_PEBS_COUNTERS];
};


@@ -237,9 +274,11 @@ extern int ds_reset_pebs(struct pebs_tracer *tracer);
 * Returns 0 on success; -Eerrno on error
 *
 * tracer: the tracer handle returned from ds_request_pebs()
 * counter: the index of the counter
 * value: the new counter reset value
 */
extern int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value);
extern int ds_set_pebs_reset(struct pebs_tracer *tracer,
			     unsigned int counter, u64 value);

/*
 * Initialization
@@ -252,21 +291,12 @@ extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *);
 */
extern void ds_switch_to(struct task_struct *prev, struct task_struct *next);

/*
 * Task clone/init and cleanup work
 */
extern void ds_copy_thread(struct task_struct *tsk, struct task_struct *father);
extern void ds_exit_thread(struct task_struct *tsk);

#else /* CONFIG_X86_DS */

struct cpuinfo_x86;
static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
static inline void ds_switch_to(struct task_struct *prev,
				struct task_struct *next) {}
static inline void ds_copy_thread(struct task_struct *tsk,
				  struct task_struct *father) {}
static inline void ds_exit_thread(struct task_struct *tsk) {}

#endif /* CONFIG_X86_DS */
#endif /* _ASM_X86_DS_H */
+28 −7
Original line number Diff line number Diff line
@@ -460,14 +460,8 @@ struct thread_struct {
	unsigned		io_bitmap_max;
/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
	unsigned long	debugctlmsr;
#ifdef CONFIG_X86_DS
/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */
	/* Debug Store context; see asm/ds.h */
	struct ds_context	*ds_ctx;
#endif /* CONFIG_X86_DS */
#ifdef CONFIG_X86_PTRACE_BTS
/* the signal to send on a bts buffer overflow */
	unsigned int	bts_ovfl_signal;
#endif /* CONFIG_X86_PTRACE_BTS */
};

static inline unsigned long native_get_debugreg(int regno)
@@ -795,6 +789,21 @@ static inline unsigned long get_debugctlmsr(void)
    return debugctlmsr;
}

static inline unsigned long get_debugctlmsr_on_cpu(int cpu)
{
	u64 debugctlmsr = 0;
	u32 val1, val2;

#ifndef CONFIG_X86_DEBUGCTLMSR
	if (boot_cpu_data.x86 < 6)
		return 0;
#endif
	rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2);
	debugctlmsr = val1 | ((u64)val2 << 32);

	return debugctlmsr;
}

static inline void update_debugctlmsr(unsigned long debugctlmsr)
{
#ifndef CONFIG_X86_DEBUGCTLMSR
@@ -804,6 +813,18 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr)
	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
}

static inline void update_debugctlmsr_on_cpu(int cpu,
					     unsigned long debugctlmsr)
{
#ifndef CONFIG_X86_DEBUGCTLMSR
	if (boot_cpu_data.x86 < 6)
		return;
#endif
	wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR,
		     (u32)((u64)debugctlmsr),
		     (u32)((u64)debugctlmsr >> 32));
}

/*
 * from system description table in BIOS. Mostly for MCA use, but
 * others may find it useful:
+4 −5
Original line number Diff line number Diff line
@@ -235,12 +235,11 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
extern int do_set_thread_area(struct task_struct *p, int idx,
			      struct user_desc __user *info, int can_allocate);

extern void x86_ptrace_untrace(struct task_struct *);
extern void x86_ptrace_fork(struct task_struct *child,
			    unsigned long clone_flags);
#ifdef CONFIG_X86_PTRACE_BTS
extern void ptrace_bts_untrace(struct task_struct *tsk);

#define arch_ptrace_untrace(tsk) x86_ptrace_untrace(tsk)
#define arch_ptrace_fork(child, flags) x86_ptrace_fork(child, flags)
#define arch_ptrace_untrace(tsk)	ptrace_bts_untrace(tsk)
#endif /* CONFIG_X86_PTRACE_BTS */

#endif /* __KERNEL__ */

Loading