Line data Source code
1 : /*
2 : * Debug Store (DS) support
3 : *
4 : * This provides a low-level interface to the hardware's Debug Store
5 : * feature that is used for branch trace store (BTS) and
6 : * precise-event based sampling (PEBS).
7 : *
8 : * It manages:
9 : * - DS and BTS hardware configuration
10 : * - buffer overflow handling (to be done)
11 : * - buffer access
12 : *
13 : * It does not do:
14 : * - security checking (is the caller allowed to trace the task)
15 : * - buffer allocation (memory accounting)
16 : *
17 : *
18 : * Copyright (C) 2007-2009 Intel Corporation.
19 : * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
20 : */
21 :
22 : #ifndef _ASM_X86_DS_H
23 : #define _ASM_X86_DS_H
24 :
25 :
26 : #include <linux/types.h>
27 : #include <linux/init.h>
28 : #include <linux/err.h>
29 :
30 :
31 : #ifdef CONFIG_X86_DS
32 :
33 : struct task_struct;
34 : struct ds_context;
35 : struct ds_tracer;
36 : struct bts_tracer;
37 : struct pebs_tracer;
38 :
39 : typedef void (*bts_ovfl_callback_t)(struct bts_tracer *);
40 : typedef void (*pebs_ovfl_callback_t)(struct pebs_tracer *);
41 :
42 :
43 : /*
44 : * A list of features plus corresponding macros to talk about them in
45 : * the ds_request function's flags parameter.
46 : *
47 : * We use the enum to index an array of corresponding control bits;
48 : * we use the macro to index a flags bit-vector.
49 : */
50 : enum ds_feature {
51 : dsf_bts = 0,
52 : dsf_bts_kernel,
53 : #define BTS_KERNEL (1 << dsf_bts_kernel)
54 : /* trace kernel-mode branches */
55 :
56 : dsf_bts_user,
57 : #define BTS_USER (1 << dsf_bts_user)
58 : /* trace user-mode branches */
59 :
60 : dsf_bts_overflow,
61 : dsf_bts_max,
62 : dsf_pebs = dsf_bts_max,
63 :
64 : dsf_pebs_max,
65 : dsf_ctl_max = dsf_pebs_max,
66 : dsf_bts_timestamps = dsf_ctl_max,
67 : #define BTS_TIMESTAMPS (1 << dsf_bts_timestamps)
68 : /* add timestamps into BTS trace */
69 :
70 : #define BTS_USER_FLAGS (BTS_KERNEL | BTS_USER | BTS_TIMESTAMPS)
71 : };
72 :
73 :
74 : /*
75 : * Request BTS or PEBS
76 : *
77 : * Due to alignement constraints, the actual buffer may be slightly
78 : * smaller than the requested or provided buffer.
79 : *
80 : * Returns a pointer to a tracer structure on success, or
81 : * ERR_PTR(errcode) on failure.
82 : *
83 : * The interrupt threshold is independent from the overflow callback
84 : * to allow users to use their own overflow interrupt handling mechanism.
85 : *
86 : * The function might sleep.
87 : *
88 : * task: the task to request recording for
89 : * cpu: the cpu to request recording for
90 : * base: the base pointer for the (non-pageable) buffer;
91 : * size: the size of the provided buffer in bytes
92 : * ovfl: pointer to a function to be called on buffer overflow;
93 : * NULL if cyclic buffer requested
94 : * th: the interrupt threshold in records from the end of the buffer;
95 : * -1 if no interrupt threshold is requested.
96 : * flags: a bit-mask of the above flags
97 : */
98 : extern struct bts_tracer *ds_request_bts_task(struct task_struct *task,
99 : void *base, size_t size,
100 : bts_ovfl_callback_t ovfl,
101 : size_t th, unsigned int flags);
102 : extern struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size,
103 : bts_ovfl_callback_t ovfl,
104 : size_t th, unsigned int flags);
105 : extern struct pebs_tracer *ds_request_pebs_task(struct task_struct *task,
106 : void *base, size_t size,
107 : pebs_ovfl_callback_t ovfl,
108 : size_t th, unsigned int flags);
109 : extern struct pebs_tracer *ds_request_pebs_cpu(int cpu,
110 : void *base, size_t size,
111 : pebs_ovfl_callback_t ovfl,
112 : size_t th, unsigned int flags);
113 :
114 : /*
115 : * Release BTS or PEBS resources
116 : * Suspend and resume BTS or PEBS tracing
117 : *
118 : * Must be called with irq's enabled.
119 : *
120 : * tracer: the tracer handle returned from ds_request_~()
121 : */
122 : extern void ds_release_bts(struct bts_tracer *tracer);
123 : extern void ds_suspend_bts(struct bts_tracer *tracer);
124 : extern void ds_resume_bts(struct bts_tracer *tracer);
125 : extern void ds_release_pebs(struct pebs_tracer *tracer);
126 : extern void ds_suspend_pebs(struct pebs_tracer *tracer);
127 : extern void ds_resume_pebs(struct pebs_tracer *tracer);
128 :
129 : /*
130 : * Release BTS or PEBS resources
131 : * Suspend and resume BTS or PEBS tracing
132 : *
133 : * Cpu tracers must call this on the traced cpu.
134 : * Task tracers must call ds_release_~_noirq() for themselves.
135 : *
136 : * May be called with irq's disabled.
137 : *
138 : * Returns 0 if successful;
139 : * -EPERM if the cpu tracer does not trace the current cpu.
140 : * -EPERM if the task tracer does not trace itself.
141 : *
142 : * tracer: the tracer handle returned from ds_request_~()
143 : */
144 : extern int ds_release_bts_noirq(struct bts_tracer *tracer);
145 : extern int ds_suspend_bts_noirq(struct bts_tracer *tracer);
146 : extern int ds_resume_bts_noirq(struct bts_tracer *tracer);
147 : extern int ds_release_pebs_noirq(struct pebs_tracer *tracer);
148 : extern int ds_suspend_pebs_noirq(struct pebs_tracer *tracer);
149 : extern int ds_resume_pebs_noirq(struct pebs_tracer *tracer);
150 :
151 :
152 : /*
153 : * The raw DS buffer state as it is used for BTS and PEBS recording.
154 : *
155 : * This is the low-level, arch-dependent interface for working
156 : * directly on the raw trace data.
157 : */
158 : struct ds_trace {
159 : /* the number of bts/pebs records */
160 : size_t n;
161 : /* the size of a bts/pebs record in bytes */
162 : size_t size;
163 : /* pointers into the raw buffer:
164 : - to the first entry */
165 : void *begin;
166 : /* - one beyond the last entry */
167 : void *end;
168 : /* - one beyond the newest entry */
169 : void *top;
170 : /* - the interrupt threshold */
171 : void *ith;
172 : /* flags given on ds_request() */
173 : unsigned int flags;
174 : };
175 :
176 : /*
177 : * An arch-independent view on branch trace data.
178 : */
179 : enum bts_qualifier {
180 : bts_invalid,
181 : #define BTS_INVALID bts_invalid
182 :
183 : bts_branch,
184 : #define BTS_BRANCH bts_branch
185 :
186 : bts_task_arrives,
187 : #define BTS_TASK_ARRIVES bts_task_arrives
188 :
189 : bts_task_departs,
190 : #define BTS_TASK_DEPARTS bts_task_departs
191 :
192 : bts_qual_bit_size = 4,
193 : bts_qual_max = (1 << bts_qual_bit_size),
194 : };
195 :
196 : struct bts_struct {
197 : __u64 qualifier;
198 : union {
199 : /* BTS_BRANCH */
200 : struct {
201 : __u64 from;
202 : __u64 to;
203 : } lbr;
204 : /* BTS_TASK_ARRIVES or BTS_TASK_DEPARTS */
205 : struct {
206 : __u64 clock;
207 : pid_t pid;
208 : } event;
209 : } variant;
210 : };
211 :
212 :
213 : /*
214 : * The BTS state.
215 : *
216 : * This gives access to the raw DS state and adds functions to provide
217 : * an arch-independent view of the BTS data.
218 : */
219 : struct bts_trace {
220 : struct ds_trace ds;
221 :
222 : int (*read)(struct bts_tracer *tracer, const void *at,
223 : struct bts_struct *out);
224 : int (*write)(struct bts_tracer *tracer, const struct bts_struct *in);
225 : };
226 :
227 :
228 : /*
229 : * The PEBS state.
230 : *
231 : * This gives access to the raw DS state and the PEBS-specific counter
232 : * reset value.
233 : */
234 : struct pebs_trace {
235 : struct ds_trace ds;
236 :
237 : /* the number of valid counters in the below array */
238 : unsigned int counters;
239 :
240 : #define MAX_PEBS_COUNTERS 4
241 : /* the counter reset value */
242 : unsigned long long counter_reset[MAX_PEBS_COUNTERS];
243 : };
244 :
245 :
246 : /*
247 : * Read the BTS or PEBS trace.
248 : *
249 : * Returns a view on the trace collected for the parameter tracer.
250 : *
251 : * The view remains valid as long as the traced task is not running or
252 : * the tracer is suspended.
253 : * Writes into the trace buffer are not reflected.
254 : *
255 : * tracer: the tracer handle returned from ds_request_~()
256 : */
257 : extern const struct bts_trace *ds_read_bts(struct bts_tracer *tracer);
258 : extern const struct pebs_trace *ds_read_pebs(struct pebs_tracer *tracer);
259 :
260 :
261 : /*
262 : * Reset the write pointer of the BTS/PEBS buffer.
263 : *
264 : * Returns 0 on success; -Eerrno on error
265 : *
266 : * tracer: the tracer handle returned from ds_request_~()
267 : */
268 : extern int ds_reset_bts(struct bts_tracer *tracer);
269 : extern int ds_reset_pebs(struct pebs_tracer *tracer);
270 :
271 : /*
272 : * Set the PEBS counter reset value.
273 : *
274 : * Returns 0 on success; -Eerrno on error
275 : *
276 : * tracer: the tracer handle returned from ds_request_pebs()
277 : * counter: the index of the counter
278 : * value: the new counter reset value
279 : */
280 : extern int ds_set_pebs_reset(struct pebs_tracer *tracer,
281 : unsigned int counter, u64 value);
282 :
283 : /*
284 : * Initialization
285 : */
286 : struct cpuinfo_x86;
287 : extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *);
288 :
289 : /*
290 : * Context switch work
291 : */
292 : extern void ds_switch_to(struct task_struct *prev, struct task_struct *next);
293 :
294 : #else /* CONFIG_X86_DS */
295 :
296 : struct cpuinfo_x86;
297 : static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
298 : static inline void ds_switch_to(struct task_struct *prev,
299 : struct task_struct *next) {}
300 :
301 1 : #endif /* CONFIG_X86_DS */
302 : #endif /* _ASM_X86_DS_H */
|