diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/hw_breakpoint.c | 87 |
1 files changed, 18 insertions, 69 deletions
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 32e1018191be..2a47514f12fd 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c | |||
@@ -289,90 +289,32 @@ int register_perf_hw_breakpoint(struct perf_event *bp) | |||
289 | return __register_perf_hw_breakpoint(bp); | 289 | return __register_perf_hw_breakpoint(bp); |
290 | } | 290 | } |
291 | 291 | ||
292 | /* | ||
293 | * Register a breakpoint bound to a task and a given cpu. | ||
294 | * If cpu is -1, the breakpoint is active for the task in every cpu | ||
295 | * If the task is -1, the breakpoint is active for every tasks in the given | ||
296 | * cpu. | ||
297 | */ | ||
298 | static struct perf_event * | ||
299 | register_user_hw_breakpoint_cpu(unsigned long addr, | ||
300 | int len, | ||
301 | int type, | ||
302 | perf_callback_t triggered, | ||
303 | pid_t pid, | ||
304 | int cpu, | ||
305 | bool active) | ||
306 | { | ||
307 | struct perf_event_attr *attr; | ||
308 | struct perf_event *bp; | ||
309 | |||
310 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | ||
311 | if (!attr) | ||
312 | return ERR_PTR(-ENOMEM); | ||
313 | |||
314 | attr->type = PERF_TYPE_BREAKPOINT; | ||
315 | attr->size = sizeof(*attr); | ||
316 | attr->bp_addr = addr; | ||
317 | attr->bp_len = len; | ||
318 | attr->bp_type = type; | ||
319 | /* | ||
320 | * Such breakpoints are used by debuggers to trigger signals when | ||
321 | * we hit the excepted memory op. We can't miss such events, they | ||
322 | * must be pinned. | ||
323 | */ | ||
324 | attr->pinned = 1; | ||
325 | |||
326 | if (!active) | ||
327 | attr->disabled = 1; | ||
328 | |||
329 | bp = perf_event_create_kernel_counter(attr, cpu, pid, triggered); | ||
330 | kfree(attr); | ||
331 | |||
332 | return bp; | ||
333 | } | ||
334 | |||
335 | /** | 292 | /** |
336 | * register_user_hw_breakpoint - register a hardware breakpoint for user space | 293 | * register_user_hw_breakpoint - register a hardware breakpoint for user space |
337 | * @addr: is the memory address that triggers the breakpoint | 294 | * @attr: breakpoint attributes |
338 | * @len: the length of the access to the memory (1 byte, 2 bytes etc...) | ||
339 | * @type: the type of the access to the memory (read/write/exec) | ||
340 | * @triggered: callback to trigger when we hit the breakpoint | 295 | * @triggered: callback to trigger when we hit the breakpoint |
341 | * @tsk: pointer to 'task_struct' of the process to which the address belongs | 296 | * @tsk: pointer to 'task_struct' of the process to which the address belongs |
342 | * @active: should we activate it while registering it | ||
343 | * | ||
344 | */ | 297 | */ |
345 | struct perf_event * | 298 | struct perf_event * |
346 | register_user_hw_breakpoint(unsigned long addr, | 299 | register_user_hw_breakpoint(struct perf_event_attr *attr, |
347 | int len, | ||
348 | int type, | ||
349 | perf_callback_t triggered, | 300 | perf_callback_t triggered, |
350 | struct task_struct *tsk, | 301 | struct task_struct *tsk) |
351 | bool active) | ||
352 | { | 302 | { |
353 | return register_user_hw_breakpoint_cpu(addr, len, type, triggered, | 303 | return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered); |
354 | tsk->pid, -1, active); | ||
355 | } | 304 | } |
356 | EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); | 305 | EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); |
357 | 306 | ||
358 | /** | 307 | /** |
359 | * modify_user_hw_breakpoint - modify a user-space hardware breakpoint | 308 | * modify_user_hw_breakpoint - modify a user-space hardware breakpoint |
360 | * @bp: the breakpoint structure to modify | 309 | * @bp: the breakpoint structure to modify |
361 | * @addr: is the memory address that triggers the breakpoint | 310 | * @attr: new breakpoint attributes |
362 | * @len: the length of the access to the memory (1 byte, 2 bytes etc...) | ||
363 | * @type: the type of the access to the memory (read/write/exec) | ||
364 | * @triggered: callback to trigger when we hit the breakpoint | 311 | * @triggered: callback to trigger when we hit the breakpoint |
365 | * @tsk: pointer to 'task_struct' of the process to which the address belongs | 312 | * @tsk: pointer to 'task_struct' of the process to which the address belongs |
366 | * @active: should we activate it while registering it | ||
367 | */ | 313 | */ |
368 | struct perf_event * | 314 | struct perf_event * |
369 | modify_user_hw_breakpoint(struct perf_event *bp, | 315 | modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr, |
370 | unsigned long addr, | ||
371 | int len, | ||
372 | int type, | ||
373 | perf_callback_t triggered, | 316 | perf_callback_t triggered, |
374 | struct task_struct *tsk, | 317 | struct task_struct *tsk) |
375 | bool active) | ||
376 | { | 318 | { |
377 | /* | 319 | /* |
378 | * FIXME: do it without unregistering | 320 | * FIXME: do it without unregistering |
@@ -381,8 +323,7 @@ modify_user_hw_breakpoint(struct perf_event *bp, | |||
381 | */ | 323 | */ |
382 | unregister_hw_breakpoint(bp); | 324 | unregister_hw_breakpoint(bp); |
383 | 325 | ||
384 | return register_user_hw_breakpoint(addr, len, type, triggered, | 326 | return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered); |
385 | tsk, active); | ||
386 | } | 327 | } |
387 | EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint); | 328 | EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint); |
388 | 329 | ||
@@ -406,8 +347,16 @@ register_kernel_hw_breakpoint_cpu(unsigned long addr, | |||
406 | int cpu, | 347 | int cpu, |
407 | bool active) | 348 | bool active) |
408 | { | 349 | { |
409 | return register_user_hw_breakpoint_cpu(addr, len, type, triggered, | 350 | DEFINE_BREAKPOINT_ATTR(attr); |
410 | -1, cpu, active); | 351 | |
352 | attr.bp_addr = addr; | ||
353 | attr.bp_len = len; | ||
354 | attr.bp_type = type; | ||
355 | |||
356 | if (!active) | ||
357 | attr.disabled = 1; | ||
358 | |||
359 | return perf_event_create_kernel_counter(&attr, cpu, -1, triggered); | ||
411 | } | 360 | } |
412 | 361 | ||
413 | /** | 362 | /** |