Lines Matching +full:ctrl +full:- +full:len

1 // SPDX-License-Identifier: GPL-2.0-only
3 * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
10 #define pr_fmt(fmt) "hw-breakpoint: " fmt
23 #include <asm/debug-monitors.h>
35 /* Currently stepping a per-CPU kernel breakpoint. */
149 return -EINVAL; in debug_exception_level()
162 struct task_struct *tsk = bp->hw.target; in is_compat_bp()
165 * tsk can be NULL for per-cpu (non-ptrace) breakpoints. in is_compat_bp()
175 * hw_breakpoint_slot_setup - Find and setup a perf slot according to
185 * -ENOSPC if no slot is available/matches
186 * -EINVAL on wrong operations parameter
216 return -EINVAL; in hw_breakpoint_slot_setup()
219 return -ENOSPC; in hw_breakpoint_slot_setup()
227 struct debug_info *debug_info = &current->thread.debug; in hw_breakpoint_control()
229 enum dbg_active_el dbg_el = debug_exception_level(info->ctrl.privilege); in hw_breakpoint_control()
230 u32 ctrl; in hw_breakpoint_control() local
232 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { in hw_breakpoint_control()
238 reg_enable = !debug_info->bps_disabled; in hw_breakpoint_control()
245 reg_enable = !debug_info->wps_disabled; in hw_breakpoint_control()
263 write_wb_reg(val_reg, i, info->address); in hw_breakpoint_control()
266 ctrl = encode_ctrl_reg(info->ctrl); in hw_breakpoint_control()
268 reg_enable ? ctrl | 0x1 : ctrl & ~0x1); in hw_breakpoint_control()
337 unsigned int len; in arch_check_bp_in_kernelspace() local
340 va = hw->address; in arch_check_bp_in_kernelspace()
341 len = get_hbp_len(hw->ctrl.len); in arch_check_bp_in_kernelspace()
343 return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); in arch_check_bp_in_kernelspace()
351 int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, in arch_bp_generic_fields() argument
355 switch (ctrl.type) { in arch_bp_generic_fields()
369 return -EINVAL; in arch_bp_generic_fields()
372 if (!ctrl.len) in arch_bp_generic_fields()
373 return -EINVAL; in arch_bp_generic_fields()
374 *offset = __ffs(ctrl.len); in arch_bp_generic_fields()
376 /* Len */ in arch_bp_generic_fields()
377 switch (ctrl.len >> *offset) { in arch_bp_generic_fields()
403 return -EINVAL; in arch_bp_generic_fields()
417 switch (attr->bp_type) { in arch_build_bp_info()
419 hw->ctrl.type = ARM_BREAKPOINT_EXECUTE; in arch_build_bp_info()
422 hw->ctrl.type = ARM_BREAKPOINT_LOAD; in arch_build_bp_info()
425 hw->ctrl.type = ARM_BREAKPOINT_STORE; in arch_build_bp_info()
428 hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; in arch_build_bp_info()
431 return -EINVAL; in arch_build_bp_info()
434 /* Len */ in arch_build_bp_info()
435 switch (attr->bp_len) { in arch_build_bp_info()
437 hw->ctrl.len = ARM_BREAKPOINT_LEN_1; in arch_build_bp_info()
440 hw->ctrl.len = ARM_BREAKPOINT_LEN_2; in arch_build_bp_info()
443 hw->ctrl.len = ARM_BREAKPOINT_LEN_3; in arch_build_bp_info()
446 hw->ctrl.len = ARM_BREAKPOINT_LEN_4; in arch_build_bp_info()
449 hw->ctrl.len = ARM_BREAKPOINT_LEN_5; in arch_build_bp_info()
452 hw->ctrl.len = ARM_BREAKPOINT_LEN_6; in arch_build_bp_info()
455 hw->ctrl.len = ARM_BREAKPOINT_LEN_7; in arch_build_bp_info()
458 hw->ctrl.len = ARM_BREAKPOINT_LEN_8; in arch_build_bp_info()
461 return -EINVAL; in arch_build_bp_info()
469 if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) { in arch_build_bp_info()
471 if (hw->ctrl.len != ARM_BREAKPOINT_LEN_2 && in arch_build_bp_info()
472 hw->ctrl.len != ARM_BREAKPOINT_LEN_4) in arch_build_bp_info()
473 return -EINVAL; in arch_build_bp_info()
474 } else if (hw->ctrl.len != ARM_BREAKPOINT_LEN_4) { in arch_build_bp_info()
479 * but we should probably return -EINVAL instead. in arch_build_bp_info()
481 hw->ctrl.len = ARM_BREAKPOINT_LEN_4; in arch_build_bp_info()
486 hw->address = attr->bp_addr; in arch_build_bp_info()
494 hw->ctrl.privilege = AARCH64_BREAKPOINT_EL1; in arch_build_bp_info()
496 hw->ctrl.privilege = AARCH64_BREAKPOINT_EL0; in arch_build_bp_info()
499 hw->ctrl.enabled = !attr->disabled; in arch_build_bp_info()
505 * Validate the arch-specific HW Breakpoint register settings.
522 * because using 64-bit unaligned addresses is deprecated for in hw_breakpoint_arch_parse()
529 if (hw->ctrl.len == ARM_BREAKPOINT_LEN_8) in hw_breakpoint_arch_parse()
533 offset = hw->address & alignment_mask; in hw_breakpoint_arch_parse()
541 if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2) in hw_breakpoint_arch_parse()
547 if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1) in hw_breakpoint_arch_parse()
552 return -EINVAL; in hw_breakpoint_arch_parse()
555 if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) in hw_breakpoint_arch_parse()
559 offset = hw->address & alignment_mask; in hw_breakpoint_arch_parse()
562 hw->address &= ~alignment_mask; in hw_breakpoint_arch_parse()
563 hw->ctrl.len <<= offset; in hw_breakpoint_arch_parse()
566 * Disallow per-task kernel breakpoints since these would in hw_breakpoint_arch_parse()
569 if (hw->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.target) in hw_breakpoint_arch_parse()
570 return -EINVAL; in hw_breakpoint_arch_parse()
578 * This is used when single-stepping after a breakpoint exception.
583 u32 ctrl; in toggle_bp_registers() local
603 privilege = counter_arch_bp(slots[i])->ctrl.privilege; in toggle_bp_registers()
607 ctrl = read_wb_reg(reg, i); in toggle_bp_registers()
609 ctrl |= 0x1; in toggle_bp_registers()
611 ctrl &= ~0x1; in toggle_bp_registers()
612 write_wb_reg(reg, i, ctrl); in toggle_bp_registers()
628 struct arch_hw_breakpoint_ctrl ctrl; in breakpoint_handler() local
632 debug_info = &current->thread.debug; in breakpoint_handler()
649 decode_ctrl_reg(ctrl_reg, &ctrl); in breakpoint_handler()
650 if (!((1 << (addr & 0x3)) & ctrl.len)) in breakpoint_handler()
653 counter_arch_bp(bp)->trigger = addr; in breakpoint_handler()
667 debug_info->bps_disabled = 1; in breakpoint_handler()
671 if (debug_info->wps_disabled) in breakpoint_handler()
675 debug_info->suspended_step = 1; in breakpoint_handler()
701 * addresses. There is no straight-forward way, short of disassembling the
713 struct arch_hw_breakpoint_ctrl *ctrl) in get_distance_from_watchpoint() argument
720 lens = __ffs(ctrl->len); in get_distance_from_watchpoint()
721 lene = __fls(ctrl->len); in get_distance_from_watchpoint()
726 return wp_low - addr; in get_distance_from_watchpoint()
728 return addr - wp_high; in get_distance_from_watchpoint()
739 info->trigger = addr; in watchpoint_report()
746 if (!user_mode(regs) && info->ctrl.privilege == AARCH64_BREAKPOINT_EL0) in watchpoint_report()
758 u64 min_dist = -1, dist; in watchpoint_handler()
763 struct arch_hw_breakpoint_ctrl ctrl; in watchpoint_handler() local
766 debug_info = &current->thread.debug; in watchpoint_handler()
790 decode_ctrl_reg(ctrl_reg, &ctrl); in watchpoint_handler()
791 dist = get_distance_from_watchpoint(addr, val, &ctrl); in watchpoint_handler()
804 if (min_dist > 0 && min_dist != -1) in watchpoint_handler()
819 debug_info->wps_disabled = 1; in watchpoint_handler()
822 if (debug_info->bps_disabled) in watchpoint_handler()
826 debug_info->suspended_step = 1; in watchpoint_handler()
849 * Handle single-step exception.
853 struct debug_info *debug_info = &current->thread.debug; in reinstall_suspended_bps()
859 * Called from single-step exception handler. in reinstall_suspended_bps()
864 if (debug_info->bps_disabled) { in reinstall_suspended_bps()
865 debug_info->bps_disabled = 0; in reinstall_suspended_bps()
870 if (debug_info->wps_disabled) { in reinstall_suspended_bps()
871 debug_info->wps_disabled = 0; in reinstall_suspended_bps()
877 if (debug_info->suspended_step) { in reinstall_suspended_bps()
878 debug_info->suspended_step = 0; in reinstall_suspended_bps()
879 /* Allow exception handling to fall-through. */ in reinstall_suspended_bps()
889 if (!debug_info->wps_disabled) in reinstall_suspended_bps()
907 * Context-switcher for restoring suspended breakpoints.
916 * 1 1 => NOTIFY_DONE. per-task bps will in hw_breakpoint_thread_switch()
922 current_debug_info = &current->thread.debug; in hw_breakpoint_thread_switch()
923 next_debug_info = &next->thread.debug; in hw_breakpoint_thread_switch()
926 if (current_debug_info->bps_disabled != next_debug_info->bps_disabled) in hw_breakpoint_thread_switch()
929 !next_debug_info->bps_disabled); in hw_breakpoint_thread_switch()
932 if (current_debug_info->wps_disabled != next_debug_info->wps_disabled) in hw_breakpoint_thread_switch()
935 !next_debug_info->wps_disabled); in hw_breakpoint_thread_switch()
946 * When a CPU goes through cold-boot, it does not have any installed in hw_breakpoint_reset()
951 * When this function is triggered on warm-boot through a CPU PM in hw_breakpoint_reset()
977 * One-time initialisation.
991 TRAP_HWBKPT, "hw-breakpoint handler"); in arch_hw_breakpoint_init()
993 TRAP_HWBKPT, "hw-watchpoint handler"); in arch_hw_breakpoint_init()