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 | 26 | |
eee3af4a MM |
27 | #include <linux/types.h> |
28 | #include <linux/init.h> | |
ca0002a1 | 29 | #include <linux/err.h> |
eee3af4a | 30 | |
eee3af4a | 31 | |
e5e8ca63 MM |
32 | #ifdef CONFIG_X86_DS |
33 | ||
93fa7636 | 34 | struct task_struct; |
ca0002a1 MM |
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 *); | |
eee3af4a | 41 | |
93fa7636 MM |
42 | /* |
43 | * Request BTS or PEBS | |
44 | * | |
45 | * Due to alignement constraints, the actual buffer may be slightly | |
46 | * smaller than the requested or provided buffer. | |
eee3af4a | 47 | * |
ca0002a1 MM |
48 | * Returns a pointer to a tracer structure on success, or |
49 | * ERR_PTR(errcode) on failure. | |
50 | * | |
51 | * The interrupt threshold is independent from the overflow callback | |
52 | * to allow users to use their own overflow interrupt handling mechanism. | |
93fa7636 MM |
53 | * |
54 | * task: the task to request recording for; | |
55 | * NULL for per-cpu recording on the current cpu | |
56 | * base: the base pointer for the (non-pageable) buffer; | |
57 | * NULL if buffer allocation requested | |
ca0002a1 | 58 | * size: the size of the requested or provided buffer in bytes |
93fa7636 MM |
59 | * ovfl: pointer to a function to be called on buffer overflow; |
60 | * NULL if cyclic buffer requested | |
ca0002a1 MM |
61 | * th: the interrupt threshold in records from the end of the buffer; |
62 | * -1 if no interrupt threshold is requested. | |
eee3af4a | 63 | */ |
ca0002a1 MM |
64 | extern struct bts_tracer *ds_request_bts(struct task_struct *task, |
65 | void *base, size_t size, | |
66 | bts_ovfl_callback_t ovfl, size_t th); | |
67 | extern struct pebs_tracer *ds_request_pebs(struct task_struct *task, | |
68 | void *base, size_t size, | |
69 | pebs_ovfl_callback_t ovfl, | |
70 | size_t th); | |
93fa7636 MM |
71 | |
72 | /* | |
73 | * Release BTS or PEBS resources | |
74 | * | |
75 | * Frees buffers allocated on ds_request. | |
76 | * | |
77 | * Returns 0 on success; -Eerrno otherwise | |
78 | * | |
ca0002a1 | 79 | * tracer: the tracer handle returned from ds_request_~() |
93fa7636 | 80 | */ |
ca0002a1 MM |
81 | extern int ds_release_bts(struct bts_tracer *tracer); |
82 | extern int ds_release_pebs(struct pebs_tracer *tracer); | |
93fa7636 MM |
83 | |
84 | /* | |
ca0002a1 | 85 | * Get the (array) index of the write pointer. |
93fa7636 MM |
86 | * (assuming an array of BTS/PEBS records) |
87 | * | |
ca0002a1 | 88 | * Returns 0 on success; -Eerrno on error |
93fa7636 | 89 | * |
ca0002a1 MM |
90 | * tracer: the tracer handle returned from ds_request_~() |
91 | * pos (out): will hold the result | |
93fa7636 | 92 | */ |
ca0002a1 MM |
93 | extern int ds_get_bts_index(struct bts_tracer *tracer, size_t *pos); |
94 | extern int ds_get_pebs_index(struct pebs_tracer *tracer, size_t *pos); | |
93fa7636 MM |
95 | |
96 | /* | |
ca0002a1 | 97 | * Get the (array) index one record beyond the end of the array. |
93fa7636 MM |
98 | * (assuming an array of BTS/PEBS records) |
99 | * | |
ca0002a1 | 100 | * Returns 0 on success; -Eerrno on error |
93fa7636 | 101 | * |
ca0002a1 MM |
102 | * tracer: the tracer handle returned from ds_request_~() |
103 | * pos (out): will hold the result | |
93fa7636 | 104 | */ |
ca0002a1 MM |
105 | extern int ds_get_bts_end(struct bts_tracer *tracer, size_t *pos); |
106 | extern int ds_get_pebs_end(struct pebs_tracer *tracer, size_t *pos); | |
93fa7636 MM |
107 | |
108 | /* | |
109 | * Provide a pointer to the BTS/PEBS record at parameter index. | |
110 | * (assuming an array of BTS/PEBS records) | |
111 | * | |
112 | * The pointer points directly into the buffer. The user is | |
113 | * responsible for copying the record. | |
114 | * | |
115 | * Returns the size of a single record on success; -Eerrno on error | |
116 | * | |
ca0002a1 | 117 | * tracer: the tracer handle returned from ds_request_~() |
93fa7636 MM |
118 | * index: the index of the requested record |
119 | * record (out): pointer to the requested record | |
120 | */ | |
ca0002a1 | 121 | extern int ds_access_bts(struct bts_tracer *tracer, |
93fa7636 | 122 | size_t index, const void **record); |
ca0002a1 | 123 | extern int ds_access_pebs(struct pebs_tracer *tracer, |
93fa7636 MM |
124 | size_t index, const void **record); |
125 | ||
126 | /* | |
127 | * Write one or more BTS/PEBS records at the write pointer index and | |
128 | * advance the write pointer. | |
129 | * | |
130 | * If size is not a multiple of the record size, trailing bytes are | |
131 | * zeroed out. | |
132 | * | |
133 | * May result in one or more overflow notifications. | |
134 | * | |
135 | * If called during overflow handling, that is, with index >= | |
136 | * interrupt threshold, the write will wrap around. | |
137 | * | |
138 | * An overflow notification is given if and when the interrupt | |
139 | * threshold is reached during or after the write. | |
140 | * | |
141 | * Returns the number of bytes written or -Eerrno. | |
142 | * | |
ca0002a1 | 143 | * tracer: the tracer handle returned from ds_request_~() |
93fa7636 MM |
144 | * buffer: the buffer to write |
145 | * size: the size of the buffer | |
146 | */ | |
ca0002a1 | 147 | extern int ds_write_bts(struct bts_tracer *tracer, |
93fa7636 | 148 | const void *buffer, size_t size); |
ca0002a1 | 149 | extern int ds_write_pebs(struct pebs_tracer *tracer, |
93fa7636 MM |
150 | const void *buffer, size_t size); |
151 | ||
93fa7636 MM |
152 | /* |
153 | * Reset the write pointer of the BTS/PEBS buffer. | |
154 | * | |
155 | * Returns 0 on success; -Eerrno on error | |
156 | * | |
ca0002a1 | 157 | * tracer: the tracer handle returned from ds_request_~() |
93fa7636 | 158 | */ |
ca0002a1 MM |
159 | extern int ds_reset_bts(struct bts_tracer *tracer); |
160 | extern int ds_reset_pebs(struct pebs_tracer *tracer); | |
93fa7636 MM |
161 | |
162 | /* | |
163 | * Clear the BTS/PEBS buffer and reset the write pointer. | |
164 | * The entire buffer will be zeroed out. | |
165 | * | |
166 | * Returns 0 on success; -Eerrno on error | |
167 | * | |
ca0002a1 | 168 | * tracer: the tracer handle returned from ds_request_~() |
93fa7636 | 169 | */ |
ca0002a1 MM |
170 | extern int ds_clear_bts(struct bts_tracer *tracer); |
171 | extern int ds_clear_pebs(struct pebs_tracer *tracer); | |
93fa7636 MM |
172 | |
173 | /* | |
174 | * Provide the PEBS counter reset value. | |
175 | * | |
176 | * Returns 0 on success; -Eerrno on error | |
177 | * | |
ca0002a1 | 178 | * tracer: the tracer handle returned from ds_request_pebs() |
93fa7636 MM |
179 | * value (out): the counter reset value |
180 | */ | |
ca0002a1 | 181 | extern int ds_get_pebs_reset(struct pebs_tracer *tracer, u64 *value); |
93fa7636 MM |
182 | |
183 | /* | |
184 | * Set the PEBS counter reset value. | |
185 | * | |
186 | * Returns 0 on success; -Eerrno on error | |
187 | * | |
ca0002a1 | 188 | * tracer: the tracer handle returned from ds_request_pebs() |
93fa7636 MM |
189 | * value: the new counter reset value |
190 | */ | |
ca0002a1 | 191 | extern int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value); |
93fa7636 MM |
192 | |
193 | /* | |
194 | * Initialization | |
195 | */ | |
196 | struct cpuinfo_x86; | |
197 | extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); | |
198 | ||
199 | ||
eee3af4a | 200 | |
93fa7636 MM |
201 | /* |
202 | * The DS context - part of struct thread_struct. | |
203 | */ | |
ca0002a1 MM |
204 | #define MAX_SIZEOF_DS (12 * 8) |
205 | ||
93fa7636 MM |
206 | struct ds_context { |
207 | /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ | |
ca0002a1 | 208 | unsigned char ds[MAX_SIZEOF_DS]; |
93fa7636 | 209 | /* the owner of the BTS and PEBS configuration, respectively */ |
ca0002a1 | 210 | struct ds_tracer *owner[2]; |
93fa7636 MM |
211 | /* use count */ |
212 | unsigned long count; | |
213 | /* a pointer to the context location inside the thread_struct | |
214 | * or the per_cpu context array */ | |
215 | struct ds_context **this; | |
216 | /* a pointer to the task owning this context, or NULL, if the | |
217 | * context is owned by a cpu */ | |
218 | struct task_struct *task; | |
eee3af4a MM |
219 | }; |
220 | ||
93fa7636 MM |
221 | /* called by exit_thread() to free leftover contexts */ |
222 | extern void ds_free(struct ds_context *context); | |
223 | ||
224 | #else /* CONFIG_X86_DS */ | |
225 | ||
e5e8ca63 MM |
226 | struct cpuinfo_x86; |
227 | static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {} | |
eee3af4a | 228 | |
93fa7636 | 229 | #endif /* CONFIG_X86_DS */ |
1965aae3 | 230 | #endif /* _ASM_X86_DS_H */ |