|
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 * - per-thread and per-cpu allocation of BTS and PEBS |
|
10 * - buffer memory allocation (optional) |
|
11 * - buffer overflow handling |
|
12 * - buffer access |
|
13 * |
|
14 * It assumes: |
|
15 * - get_task_struct on all parameter tasks |
|
16 * - current is allowed to trace parameter tasks |
|
17 * |
|
18 * |
|
19 * Copyright (C) 2007-2008 Intel Corporation. |
|
20 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008 |
|
21 */ |
|
22 |
|
23 #ifndef _ASM_X86_DS_H |
|
24 #define _ASM_X86_DS_H |
|
25 |
|
26 |
|
27 #include <linux/types.h> |
|
28 #include <linux/init.h> |
|
29 |
|
30 |
|
31 #ifdef CONFIG_X86_DS |
|
32 |
|
33 struct task_struct; |
|
34 |
|
35 /* |
|
36 * Request BTS or PEBS |
|
37 * |
|
38 * Due to alignement constraints, the actual buffer may be slightly |
|
39 * smaller than the requested or provided buffer. |
|
40 * |
|
41 * Returns 0 on success; -Eerrno otherwise |
|
42 * |
|
43 * task: the task to request recording for; |
|
44 * NULL for per-cpu recording on the current cpu |
|
45 * base: the base pointer for the (non-pageable) buffer; |
|
46 * NULL if buffer allocation requested |
|
47 * size: the size of the requested or provided buffer |
|
48 * ovfl: pointer to a function to be called on buffer overflow; |
|
49 * NULL if cyclic buffer requested |
|
50 */ |
|
51 typedef void (*ds_ovfl_callback_t)(struct task_struct *); |
|
52 extern int ds_request_bts(struct task_struct *task, void *base, size_t size, |
|
53 ds_ovfl_callback_t ovfl); |
|
54 extern int ds_request_pebs(struct task_struct *task, void *base, size_t size, |
|
55 ds_ovfl_callback_t ovfl); |
|
56 |
|
57 /* |
|
58 * Release BTS or PEBS resources |
|
59 * |
|
60 * Frees buffers allocated on ds_request. |
|
61 * |
|
62 * Returns 0 on success; -Eerrno otherwise |
|
63 * |
|
64 * task: the task to release resources for; |
|
65 * NULL to release resources for the current cpu |
|
66 */ |
|
67 extern int ds_release_bts(struct task_struct *task); |
|
68 extern int ds_release_pebs(struct task_struct *task); |
|
69 |
|
70 /* |
|
71 * Return the (array) index of the write pointer. |
|
72 * (assuming an array of BTS/PEBS records) |
|
73 * |
|
74 * Returns -Eerrno on error |
|
75 * |
|
76 * task: the task to access; |
|
77 * NULL to access the current cpu |
|
78 * pos (out): if not NULL, will hold the result |
|
79 */ |
|
80 extern int ds_get_bts_index(struct task_struct *task, size_t *pos); |
|
81 extern int ds_get_pebs_index(struct task_struct *task, size_t *pos); |
|
82 |
|
83 /* |
|
84 * Return the (array) index one record beyond the end of the array. |
|
85 * (assuming an array of BTS/PEBS records) |
|
86 * |
|
87 * Returns -Eerrno on error |
|
88 * |
|
89 * task: the task to access; |
|
90 * NULL to access the current cpu |
|
91 * pos (out): if not NULL, will hold the result |
|
92 */ |
|
93 extern int ds_get_bts_end(struct task_struct *task, size_t *pos); |
|
94 extern int ds_get_pebs_end(struct task_struct *task, size_t *pos); |
|
95 |
|
96 /* |
|
97 * Provide a pointer to the BTS/PEBS record at parameter index. |
|
98 * (assuming an array of BTS/PEBS records) |
|
99 * |
|
100 * The pointer points directly into the buffer. The user is |
|
101 * responsible for copying the record. |
|
102 * |
|
103 * Returns the size of a single record on success; -Eerrno on error |
|
104 * |
|
105 * task: the task to access; |
|
106 * NULL to access the current cpu |
|
107 * index: the index of the requested record |
|
108 * record (out): pointer to the requested record |
|
109 */ |
|
110 extern int ds_access_bts(struct task_struct *task, |
|
111 size_t index, const void **record); |
|
112 extern int ds_access_pebs(struct task_struct *task, |
|
113 size_t index, const void **record); |
|
114 |
|
115 /* |
|
116 * Write one or more BTS/PEBS records at the write pointer index and |
|
117 * advance the write pointer. |
|
118 * |
|
119 * If size is not a multiple of the record size, trailing bytes are |
|
120 * zeroed out. |
|
121 * |
|
122 * May result in one or more overflow notifications. |
|
123 * |
|
124 * If called during overflow handling, that is, with index >= |
|
125 * interrupt threshold, the write will wrap around. |
|
126 * |
|
127 * An overflow notification is given if and when the interrupt |
|
128 * threshold is reached during or after the write. |
|
129 * |
|
130 * Returns the number of bytes written or -Eerrno. |
|
131 * |
|
132 * task: the task to access; |
|
133 * NULL to access the current cpu |
|
134 * buffer: the buffer to write |
|
135 * size: the size of the buffer |
|
136 */ |
|
137 extern int ds_write_bts(struct task_struct *task, |
|
138 const void *buffer, size_t size); |
|
139 extern int ds_write_pebs(struct task_struct *task, |
|
140 const void *buffer, size_t size); |
|
141 |
|
142 /* |
|
143 * Same as ds_write_bts/pebs, but omit ownership checks. |
|
144 * |
|
145 * This is needed to have some other task than the owner of the |
|
146 * BTS/PEBS buffer or the parameter task itself write into the |
|
147 * respective buffer. |
|
148 */ |
|
149 extern int ds_unchecked_write_bts(struct task_struct *task, |
|
150 const void *buffer, size_t size); |
|
151 extern int ds_unchecked_write_pebs(struct task_struct *task, |
|
152 const void *buffer, size_t size); |
|
153 |
|
154 /* |
|
155 * Reset the write pointer of the BTS/PEBS buffer. |
|
156 * |
|
157 * Returns 0 on success; -Eerrno on error |
|
158 * |
|
159 * task: the task to access; |
|
160 * NULL to access the current cpu |
|
161 */ |
|
162 extern int ds_reset_bts(struct task_struct *task); |
|
163 extern int ds_reset_pebs(struct task_struct *task); |
|
164 |
|
165 /* |
|
166 * Clear the BTS/PEBS buffer and reset the write pointer. |
|
167 * The entire buffer will be zeroed out. |
|
168 * |
|
169 * Returns 0 on success; -Eerrno on error |
|
170 * |
|
171 * task: the task to access; |
|
172 * NULL to access the current cpu |
|
173 */ |
|
174 extern int ds_clear_bts(struct task_struct *task); |
|
175 extern int ds_clear_pebs(struct task_struct *task); |
|
176 |
|
177 /* |
|
178 * Provide the PEBS counter reset value. |
|
179 * |
|
180 * Returns 0 on success; -Eerrno on error |
|
181 * |
|
182 * task: the task to access; |
|
183 * NULL to access the current cpu |
|
184 * value (out): the counter reset value |
|
185 */ |
|
186 extern int ds_get_pebs_reset(struct task_struct *task, u64 *value); |
|
187 |
|
188 /* |
|
189 * Set the PEBS counter reset value. |
|
190 * |
|
191 * Returns 0 on success; -Eerrno on error |
|
192 * |
|
193 * task: the task to access; |
|
194 * NULL to access the current cpu |
|
195 * value: the new counter reset value |
|
196 */ |
|
197 extern int ds_set_pebs_reset(struct task_struct *task, u64 value); |
|
198 |
|
199 /* |
|
200 * Initialization |
|
201 */ |
|
202 struct cpuinfo_x86; |
|
203 extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); |
|
204 |
|
205 |
|
206 |
|
207 /* |
|
208 * The DS context - part of struct thread_struct. |
|
209 */ |
|
210 struct ds_context { |
|
211 /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ |
|
212 unsigned char *ds; |
|
213 /* the owner of the BTS and PEBS configuration, respectively */ |
|
214 struct task_struct *owner[2]; |
|
215 /* buffer overflow notification function for BTS and PEBS */ |
|
216 ds_ovfl_callback_t callback[2]; |
|
217 /* the original buffer address */ |
|
218 void *buffer[2]; |
|
219 /* the number of allocated pages for on-request allocated buffers */ |
|
220 unsigned int pages[2]; |
|
221 /* use count */ |
|
222 unsigned long count; |
|
223 /* a pointer to the context location inside the thread_struct |
|
224 * or the per_cpu context array */ |
|
225 struct ds_context **this; |
|
226 /* a pointer to the task owning this context, or NULL, if the |
|
227 * context is owned by a cpu */ |
|
228 struct task_struct *task; |
|
229 }; |
|
230 |
|
231 /* called by exit_thread() to free leftover contexts */ |
|
232 extern void ds_free(struct ds_context *context); |
|
233 |
|
234 #else /* CONFIG_X86_DS */ |
|
235 |
|
236 struct cpuinfo_x86; |
|
237 static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {} |
|
238 |
|
239 #endif /* CONFIG_X86_DS */ |
|
240 #endif /* _ASM_X86_DS_H */ |