diff options
author | Markus Metzger <markus.t.metzger@intel.com> | 2008-11-25 03:01:25 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-25 11:31:11 -0500 |
commit | ca0002a179bfa532d009a9272d619732872c49bd (patch) | |
tree | 9a9ca02164dfb2c13afaa38ab67f3f15d8dd5ce8 /arch/x86/include/asm/ds.h | |
parent | 7d55718b0c19ba611241c330f688ee824e9bab79 (diff) |
x86, bts: base in-kernel ds interface on handles
Impact: generalize the DS code to shared buffers
Change the in-kernel ds.h interface to identify the tracer via a
handle returned on ds_request_~().
Tracers used to be identified via their task_struct.
The changes are required to allow DS to be shared between different
tasks, which is needed for perfmon2 and for ftrace.
For ptrace, the handle is stored in the traced task's task_struct.
This should probably go into a (arch-specific) ptrace context some
time.
Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/include/asm/ds.h')
-rw-r--r-- | arch/x86/include/asm/ds.h | 124 |
1 files changed, 57 insertions, 67 deletions
diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h index a95008457ea..0af997de5f0 100644 --- a/arch/x86/include/asm/ds.h +++ b/arch/x86/include/asm/ds.h | |||
@@ -26,11 +26,18 @@ | |||
26 | 26 | ||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/err.h> | ||
29 | 30 | ||
30 | 31 | ||
31 | #ifdef CONFIG_X86_DS | 32 | #ifdef CONFIG_X86_DS |
32 | 33 | ||
33 | struct task_struct; | 34 | struct task_struct; |
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 *); | ||
34 | 41 | ||
35 | /* | 42 | /* |
36 | * Request BTS or PEBS | 43 | * Request BTS or PEBS |
@@ -38,21 +45,29 @@ struct task_struct; | |||
38 | * Due to alignement constraints, the actual buffer may be slightly | 45 | * Due to alignement constraints, the actual buffer may be slightly |
39 | * smaller than the requested or provided buffer. | 46 | * smaller than the requested or provided buffer. |
40 | * | 47 | * |
41 | * Returns 0 on success; -Eerrno otherwise | 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. | ||
42 | * | 53 | * |
43 | * task: the task to request recording for; | 54 | * task: the task to request recording for; |
44 | * NULL for per-cpu recording on the current cpu | 55 | * NULL for per-cpu recording on the current cpu |
45 | * base: the base pointer for the (non-pageable) buffer; | 56 | * base: the base pointer for the (non-pageable) buffer; |
46 | * NULL if buffer allocation requested | 57 | * NULL if buffer allocation requested |
47 | * size: the size of the requested or provided buffer | 58 | * size: the size of the requested or provided buffer in bytes |
48 | * ovfl: pointer to a function to be called on buffer overflow; | 59 | * ovfl: pointer to a function to be called on buffer overflow; |
49 | * NULL if cyclic buffer requested | 60 | * NULL if cyclic buffer requested |
61 | * th: the interrupt threshold in records from the end of the buffer; | ||
62 | * -1 if no interrupt threshold is requested. | ||
50 | */ | 63 | */ |
51 | typedef void (*ds_ovfl_callback_t)(struct task_struct *); | 64 | extern struct bts_tracer *ds_request_bts(struct task_struct *task, |
52 | extern int ds_request_bts(struct task_struct *task, void *base, size_t size, | 65 | void *base, size_t size, |
53 | ds_ovfl_callback_t ovfl); | 66 | bts_ovfl_callback_t ovfl, size_t th); |
54 | extern int ds_request_pebs(struct task_struct *task, void *base, size_t size, | 67 | extern struct pebs_tracer *ds_request_pebs(struct task_struct *task, |
55 | ds_ovfl_callback_t ovfl); | 68 | void *base, size_t size, |
69 | pebs_ovfl_callback_t ovfl, | ||
70 | size_t th); | ||
56 | 71 | ||
57 | /* | 72 | /* |
58 | * Release BTS or PEBS resources | 73 | * Release BTS or PEBS resources |
@@ -61,37 +76,34 @@ extern int ds_request_pebs(struct task_struct *task, void *base, size_t size, | |||
61 | * | 76 | * |
62 | * Returns 0 on success; -Eerrno otherwise | 77 | * Returns 0 on success; -Eerrno otherwise |
63 | * | 78 | * |
64 | * task: the task to release resources for; | 79 | * tracer: the tracer handle returned from ds_request_~() |
65 | * NULL to release resources for the current cpu | ||
66 | */ | 80 | */ |
67 | extern int ds_release_bts(struct task_struct *task); | 81 | extern int ds_release_bts(struct bts_tracer *tracer); |
68 | extern int ds_release_pebs(struct task_struct *task); | 82 | extern int ds_release_pebs(struct pebs_tracer *tracer); |
69 | 83 | ||
70 | /* | 84 | /* |
71 | * Return the (array) index of the write pointer. | 85 | * Get the (array) index of the write pointer. |
72 | * (assuming an array of BTS/PEBS records) | 86 | * (assuming an array of BTS/PEBS records) |
73 | * | 87 | * |
74 | * Returns -Eerrno on error | 88 | * Returns 0 on success; -Eerrno on error |
75 | * | 89 | * |
76 | * task: the task to access; | 90 | * tracer: the tracer handle returned from ds_request_~() |
77 | * NULL to access the current cpu | 91 | * pos (out): will hold the result |
78 | * pos (out): if not NULL, will hold the result | ||
79 | */ | 92 | */ |
80 | extern int ds_get_bts_index(struct task_struct *task, size_t *pos); | 93 | extern int ds_get_bts_index(struct bts_tracer *tracer, size_t *pos); |
81 | extern int ds_get_pebs_index(struct task_struct *task, size_t *pos); | 94 | extern int ds_get_pebs_index(struct pebs_tracer *tracer, size_t *pos); |
82 | 95 | ||
83 | /* | 96 | /* |
84 | * Return the (array) index one record beyond the end of the array. | 97 | * Get the (array) index one record beyond the end of the array. |
85 | * (assuming an array of BTS/PEBS records) | 98 | * (assuming an array of BTS/PEBS records) |
86 | * | 99 | * |
87 | * Returns -Eerrno on error | 100 | * Returns 0 on success; -Eerrno on error |
88 | * | 101 | * |
89 | * task: the task to access; | 102 | * tracer: the tracer handle returned from ds_request_~() |
90 | * NULL to access the current cpu | 103 | * pos (out): will hold the result |
91 | * pos (out): if not NULL, will hold the result | ||
92 | */ | 104 | */ |
93 | extern int ds_get_bts_end(struct task_struct *task, size_t *pos); | 105 | extern int ds_get_bts_end(struct bts_tracer *tracer, size_t *pos); |
94 | extern int ds_get_pebs_end(struct task_struct *task, size_t *pos); | 106 | extern int ds_get_pebs_end(struct pebs_tracer *tracer, size_t *pos); |
95 | 107 | ||
96 | /* | 108 | /* |
97 | * Provide a pointer to the BTS/PEBS record at parameter index. | 109 | * Provide a pointer to the BTS/PEBS record at parameter index. |
@@ -102,14 +114,13 @@ extern int ds_get_pebs_end(struct task_struct *task, size_t *pos); | |||
102 | * | 114 | * |
103 | * Returns the size of a single record on success; -Eerrno on error | 115 | * Returns the size of a single record on success; -Eerrno on error |
104 | * | 116 | * |
105 | * task: the task to access; | 117 | * tracer: the tracer handle returned from ds_request_~() |
106 | * NULL to access the current cpu | ||
107 | * index: the index of the requested record | 118 | * index: the index of the requested record |
108 | * record (out): pointer to the requested record | 119 | * record (out): pointer to the requested record |
109 | */ | 120 | */ |
110 | extern int ds_access_bts(struct task_struct *task, | 121 | extern int ds_access_bts(struct bts_tracer *tracer, |
111 | size_t index, const void **record); | 122 | size_t index, const void **record); |
112 | extern int ds_access_pebs(struct task_struct *task, | 123 | extern int ds_access_pebs(struct pebs_tracer *tracer, |
113 | size_t index, const void **record); | 124 | size_t index, const void **record); |
114 | 125 | ||
115 | /* | 126 | /* |
@@ -129,38 +140,24 @@ extern int ds_access_pebs(struct task_struct *task, | |||
129 | * | 140 | * |
130 | * Returns the number of bytes written or -Eerrno. | 141 | * Returns the number of bytes written or -Eerrno. |
131 | * | 142 | * |
132 | * task: the task to access; | 143 | * tracer: the tracer handle returned from ds_request_~() |
133 | * NULL to access the current cpu | ||
134 | * buffer: the buffer to write | 144 | * buffer: the buffer to write |
135 | * size: the size of the buffer | 145 | * size: the size of the buffer |
136 | */ | 146 | */ |
137 | extern int ds_write_bts(struct task_struct *task, | 147 | extern int ds_write_bts(struct bts_tracer *tracer, |
138 | const void *buffer, size_t size); | 148 | const void *buffer, size_t size); |
139 | extern int ds_write_pebs(struct task_struct *task, | 149 | extern int ds_write_pebs(struct pebs_tracer *tracer, |
140 | const void *buffer, size_t size); | 150 | const void *buffer, size_t size); |
141 | 151 | ||
142 | /* | 152 | /* |
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. | 153 | * Reset the write pointer of the BTS/PEBS buffer. |
156 | * | 154 | * |
157 | * Returns 0 on success; -Eerrno on error | 155 | * Returns 0 on success; -Eerrno on error |
158 | * | 156 | * |
159 | * task: the task to access; | 157 | * tracer: the tracer handle returned from ds_request_~() |
160 | * NULL to access the current cpu | ||
161 | */ | 158 | */ |
162 | extern int ds_reset_bts(struct task_struct *task); | 159 | extern int ds_reset_bts(struct bts_tracer *tracer); |
163 | extern int ds_reset_pebs(struct task_struct *task); | 160 | extern int ds_reset_pebs(struct pebs_tracer *tracer); |
164 | 161 | ||
165 | /* | 162 | /* |
166 | * Clear the BTS/PEBS buffer and reset the write pointer. | 163 | * Clear the BTS/PEBS buffer and reset the write pointer. |
@@ -168,33 +165,30 @@ extern int ds_reset_pebs(struct task_struct *task); | |||
168 | * | 165 | * |
169 | * Returns 0 on success; -Eerrno on error | 166 | * Returns 0 on success; -Eerrno on error |
170 | * | 167 | * |
171 | * task: the task to access; | 168 | * tracer: the tracer handle returned from ds_request_~() |
172 | * NULL to access the current cpu | ||
173 | */ | 169 | */ |
174 | extern int ds_clear_bts(struct task_struct *task); | 170 | extern int ds_clear_bts(struct bts_tracer *tracer); |
175 | extern int ds_clear_pebs(struct task_struct *task); | 171 | extern int ds_clear_pebs(struct pebs_tracer *tracer); |
176 | 172 | ||
177 | /* | 173 | /* |
178 | * Provide the PEBS counter reset value. | 174 | * Provide the PEBS counter reset value. |
179 | * | 175 | * |
180 | * Returns 0 on success; -Eerrno on error | 176 | * Returns 0 on success; -Eerrno on error |
181 | * | 177 | * |
182 | * task: the task to access; | 178 | * tracer: the tracer handle returned from ds_request_pebs() |
183 | * NULL to access the current cpu | ||
184 | * value (out): the counter reset value | 179 | * value (out): the counter reset value |
185 | */ | 180 | */ |
186 | extern int ds_get_pebs_reset(struct task_struct *task, u64 *value); | 181 | extern int ds_get_pebs_reset(struct pebs_tracer *tracer, u64 *value); |
187 | 182 | ||
188 | /* | 183 | /* |
189 | * Set the PEBS counter reset value. | 184 | * Set the PEBS counter reset value. |
190 | * | 185 | * |
191 | * Returns 0 on success; -Eerrno on error | 186 | * Returns 0 on success; -Eerrno on error |
192 | * | 187 | * |
193 | * task: the task to access; | 188 | * tracer: the tracer handle returned from ds_request_pebs() |
194 | * NULL to access the current cpu | ||
195 | * value: the new counter reset value | 189 | * value: the new counter reset value |
196 | */ | 190 | */ |
197 | extern int ds_set_pebs_reset(struct task_struct *task, u64 value); | 191 | extern int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value); |
198 | 192 | ||
199 | /* | 193 | /* |
200 | * Initialization | 194 | * Initialization |
@@ -207,17 +201,13 @@ extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); | |||
207 | /* | 201 | /* |
208 | * The DS context - part of struct thread_struct. | 202 | * The DS context - part of struct thread_struct. |
209 | */ | 203 | */ |
204 | #define MAX_SIZEOF_DS (12 * 8) | ||
205 | |||
210 | struct ds_context { | 206 | struct ds_context { |
211 | /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ | 207 | /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ |
212 | unsigned char *ds; | 208 | unsigned char ds[MAX_SIZEOF_DS]; |
213 | /* the owner of the BTS and PEBS configuration, respectively */ | 209 | /* the owner of the BTS and PEBS configuration, respectively */ |
214 | struct task_struct *owner[2]; | 210 | struct ds_tracer *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 */ | 211 | /* use count */ |
222 | unsigned long count; | 212 | unsigned long count; |
223 | /* a pointer to the context location inside the thread_struct | 213 | /* a pointer to the context location inside the thread_struct |