Lines Matching +full:hardware +full:- +full:triggered

1 // SPDX-License-Identifier: GPL-2.0+
15 * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
17 * This file contains the arch-independent routines.
45 /* Number of non-pinned cpu/task breakpoints in a cpu */
62 /* Gather the number of total pinned and un-pinned bp in a cpuset */
90 unsigned int *tsk_pinned = get_bp_info(cpu, type)->tsk_pinned; in max_task_bp_pinned()
93 for (i = nr_slots[type] - 1; i >= 0; i--) { in max_task_bp_pinned()
107 struct task_struct *tsk = bp->hw.target; in task_bp_pinned()
112 if (iter->hw.target == tsk && in task_bp_pinned()
113 find_slot_idx(iter->attr.bp_type) == type && in task_bp_pinned()
114 (iter->cpu < 0 || cpu == iter->cpu)) in task_bp_pinned()
123 if (bp->cpu >= 0) in cpumask_of_bp()
124 return cpumask_of(bp->cpu); in cpumask_of_bp()
129 * Report the number of pinned/un-pinned breakpoints we have in
130 * a given cpu (cpu > -1) or in all of them (cpu = -1).
143 nr = info->cpu_pinned; in fetch_bp_busy_slots()
144 if (!bp->hw.target) in fetch_bp_busy_slots()
149 if (nr > slots->pinned) in fetch_bp_busy_slots()
150 slots->pinned = nr; in fetch_bp_busy_slots()
152 nr = info->flexible; in fetch_bp_busy_slots()
153 if (nr > slots->flexible) in fetch_bp_busy_slots()
154 slots->flexible = nr; in fetch_bp_busy_slots()
166 slots->pinned += weight; in fetch_this_slot()
175 unsigned int *tsk_pinned = get_bp_info(cpu, type)->tsk_pinned; in toggle_bp_task_slot()
178 old_idx = task_bp_pinned(cpu, bp, type) - 1; in toggle_bp_task_slot()
182 tsk_pinned[old_idx]--; in toggle_bp_task_slot()
198 weight = -weight; in toggle_bp_slot()
201 if (!bp->hw.target) { in toggle_bp_slot()
202 get_bp_info(bp->cpu, type)->cpu_pinned += weight; in toggle_bp_slot()
211 list_add_tail(&bp->hw.bp_list, &bp_task_head); in toggle_bp_slot()
213 list_del(&bp->hw.bp_list); in toggle_bp_slot()
226 * Function to perform processor-specific cleanup during unregistration
239 * == Non-pinned counter == (Considered as pinned for now)
241 * - If attached to a single cpu, check:
243 * (per_cpu(info->flexible, cpu) || (per_cpu(info->cpu_pinned, cpu)
244 * + max(per_cpu(info->tsk_pinned, cpu)))) < HBP_NUM
246 * -> If there are already non-pinned counters in this cpu, it means
252 * - If attached to every cpus, check:
254 * (per_cpu(info->flexible, *) || (max(per_cpu(info->cpu_pinned, *))
255 * + max(per_cpu(info->tsk_pinned, *)))) < HBP_NUM
257 * -> This is roughly the same, except we check the number of per cpu
264 * - If attached to a single cpu, check:
266 * ((per_cpu(info->flexible, cpu) > 1) + per_cpu(info->cpu_pinned, cpu)
267 * + max(per_cpu(info->tsk_pinned, cpu))) < HBP_NUM
269 * -> Same checks as before. But now the info->flexible, if any, must keep
272 * - If attached to every cpus, check:
274 * ((per_cpu(info->flexible, *) > 1) + max(per_cpu(info->cpu_pinned, *))
275 * + max(per_cpu(info->tsk_pinned, *))) < HBP_NUM
286 return -ENOMEM; in __reserve_bp_slot()
291 return -EINVAL; in __reserve_bp_slot()
305 return -ENOSPC; in __reserve_bp_slot()
322 ret = __reserve_bp_slot(bp, bp->attr.bp_type); in reserve_bp_slot()
346 __release_bp_slot(bp, bp->attr.bp_type); in release_bp_slot()
391 return -1; in dbg_reserve_bp_slot()
393 return __reserve_bp_slot(bp, bp->attr.bp_type); in dbg_reserve_bp_slot()
399 return -1; in dbg_release_bp_slot()
401 __release_bp_slot(bp, bp->attr.bp_type); in dbg_release_bp_slot()
417 if (attr->exclude_kernel) in hw_breakpoint_parse()
418 return -EINVAL; in hw_breakpoint_parse()
424 return -EPERM; in hw_breakpoint_parse()
439 err = hw_breakpoint_parse(bp, &bp->attr, &hw); in register_perf_hw_breakpoint()
445 bp->hw.info = hw; in register_perf_hw_breakpoint()
451 * register_user_hw_breakpoint - register a hardware breakpoint for user space
453 * @triggered: callback to trigger when we hit the breakpoint
454 * @context: context data could be used in the triggered callback
459 perf_overflow_handler_t triggered, in register_user_hw_breakpoint() argument
463 return perf_event_create_kernel_counter(attr, -1, tsk, triggered, in register_user_hw_breakpoint()
471 to->bp_addr = from->bp_addr; in hw_breakpoint_copy_attr()
472 to->bp_type = from->bp_type; in hw_breakpoint_copy_attr()
473 to->bp_len = from->bp_len; in hw_breakpoint_copy_attr()
474 to->disabled = from->disabled; in hw_breakpoint_copy_attr()
491 old_attr = bp->attr; in modify_user_hw_breakpoint_check()
494 return -EINVAL; in modify_user_hw_breakpoint_check()
497 if (bp->attr.bp_type != attr->bp_type) { in modify_user_hw_breakpoint_check()
498 err = modify_bp_slot(bp, bp->attr.bp_type, attr->bp_type); in modify_user_hw_breakpoint_check()
503 hw_breakpoint_copy_attr(&bp->attr, attr); in modify_user_hw_breakpoint_check()
504 bp->hw.info = hw; in modify_user_hw_breakpoint_check()
510 * modify_user_hw_breakpoint - modify a user-space hardware breakpoint
524 if (irqs_disabled() && bp->ctx && bp->ctx->task == current) in modify_user_hw_breakpoint()
531 if (!bp->attr.disabled) in modify_user_hw_breakpoint()
539 * unregister_hw_breakpoint - unregister a user-space hardware breakpoint
551 * register_wide_hw_breakpoint - register a wide breakpoint in the kernel
553 * @triggered: callback to trigger when we hit the breakpoint
554 * @context: context data could be used in the triggered callback
560 perf_overflow_handler_t triggered, in register_wide_hw_breakpoint() argument
569 return (void __percpu __force *)ERR_PTR(-ENOMEM); in register_wide_hw_breakpoint()
574 triggered, context); in register_wide_hw_breakpoint()
593 * unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
622 if (bp->attr.type != PERF_TYPE_BREAKPOINT) in hw_breakpoint_event_init()
623 return -ENOENT; in hw_breakpoint_event_init()
629 return -EOPNOTSUPP; in hw_breakpoint_event_init()
635 bp->destroy = bp_perf_event_destroy; in hw_breakpoint_event_init()
643 bp->hw.state = PERF_HES_STOPPED; in hw_breakpoint_add()
646 bp->hw.last_period = bp->hw.sample_period; in hw_breakpoint_add()
660 bp->hw.state = 0; in hw_breakpoint_start()
665 bp->hw.state = PERF_HES_STOPPED; in hw_breakpoint_stop()
691 info->tsk_pinned = kcalloc(nr_slots[i], sizeof(int), in init_hw_breakpoint()
693 if (!info->tsk_pinned) in init_hw_breakpoint()
707 kfree(get_bp_info(err_cpu, i)->tsk_pinned); in init_hw_breakpoint()
712 return -ENOMEM; in init_hw_breakpoint()