aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/hw_breakpoint.c87
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 */
298static struct perf_event *
299register_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 */
345struct perf_event * 298struct perf_event *
346register_user_hw_breakpoint(unsigned long addr, 299register_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}
356EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); 305EXPORT_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 */
368struct perf_event * 314struct perf_event *
369modify_user_hw_breakpoint(struct perf_event *bp, 315modify_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}
387EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint); 328EXPORT_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/**