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