21 #define pr_fmt(fmt) "hw-breakpoint: " fmt
23 #include <linux/errno.h>
24 #include <linux/hw_breakpoint.h>
25 #include <linux/perf_event.h>
26 #include <linux/ptrace.h>
29 #include <asm/compat.h>
30 #include <asm/current.h>
32 #include <asm/hw_breakpoint.h>
33 #include <asm/kdebug.h>
34 #include <asm/traps.h>
35 #include <asm/cputype.h>
36 #include <asm/system_misc.h>
48 static int core_num_brps;
49 static int core_num_wrps;
52 static int get_num_brps(
void)
58 static int get_num_wrps(
void)
71 return get_num_brps();
73 return get_num_wrps();
80 #define READ_WB_REG_CASE(OFF, N, REG, VAL) \
82 AARCH64_DBG_READ(N, REG, VAL); \
85 #define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \
87 AARCH64_DBG_WRITE(N, REG, VAL); \
90 #define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \
91 READ_WB_REG_CASE(OFF, 0, REG, VAL); \
92 READ_WB_REG_CASE(OFF, 1, REG, VAL); \
93 READ_WB_REG_CASE(OFF, 2, REG, VAL); \
94 READ_WB_REG_CASE(OFF, 3, REG, VAL); \
95 READ_WB_REG_CASE(OFF, 4, REG, VAL); \
96 READ_WB_REG_CASE(OFF, 5, REG, VAL); \
97 READ_WB_REG_CASE(OFF, 6, REG, VAL); \
98 READ_WB_REG_CASE(OFF, 7, REG, VAL); \
99 READ_WB_REG_CASE(OFF, 8, REG, VAL); \
100 READ_WB_REG_CASE(OFF, 9, REG, VAL); \
101 READ_WB_REG_CASE(OFF, 10, REG, VAL); \
102 READ_WB_REG_CASE(OFF, 11, REG, VAL); \
103 READ_WB_REG_CASE(OFF, 12, REG, VAL); \
104 READ_WB_REG_CASE(OFF, 13, REG, VAL); \
105 READ_WB_REG_CASE(OFF, 14, REG, VAL); \
106 READ_WB_REG_CASE(OFF, 15, REG, VAL)
108 #define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \
109 WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \
110 WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \
111 WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \
112 WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \
113 WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \
114 WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \
115 WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \
116 WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \
117 WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \
118 WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \
119 WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \
120 WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \
121 WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \
122 WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \
123 WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \
124 WRITE_WB_REG_CASE(OFF, 15, REG, VAL)
126 static u64 read_wb_reg(
int reg,
int n)
136 pr_warning(
"attempt to read from unknown breakpoint register %d\n", n);
142 static void write_wb_reg(
int reg,
int n,
u64 val)
150 pr_warning(
"attempt to write to unknown breakpoint register %d\n", n);
159 static enum debug_el debug_exception_level(
int privilege)
162 case AARCH64_BREAKPOINT_EL0:
163 return DBG_ACTIVE_EL0;
164 case AARCH64_BREAKPOINT_EL1:
165 return DBG_ACTIVE_EL1;
167 pr_warning(
"invalid breakpoint privilege level %d\n", privilege);
180 int i, max_slots,
ctrl_reg, val_reg, reg_enable;
183 if (info->ctrl.
type == ARM_BREAKPOINT_EXECUTE) {
185 ctrl_reg = AARCH64_DBG_REG_BCR;
186 val_reg = AARCH64_DBG_REG_BVR;
188 max_slots = core_num_brps;
189 reg_enable = !debug_info->bps_disabled;
192 ctrl_reg = AARCH64_DBG_REG_WCR;
193 val_reg = AARCH64_DBG_REG_WVR;
195 max_slots = core_num_wrps;
196 reg_enable = !debug_info->wps_disabled;
199 for (i = 0; i < max_slots; ++
i) {
208 if (
WARN_ONCE(i == max_slots,
"Can't find any breakpoint slot"))
215 write_wb_reg(val_reg, i, info->
address);
218 ctrl = encode_ctrl_reg(info->ctrl);
219 write_wb_reg(ctrl_reg, i, reg_enable ? ctrl | 0x1 : ctrl & ~0x1);
228 int i, max_slots,
base;
230 if (info->ctrl.
type == ARM_BREAKPOINT_EXECUTE) {
232 base = AARCH64_DBG_REG_BCR;
234 max_slots = core_num_brps;
237 base = AARCH64_DBG_REG_WCR;
239 max_slots = core_num_wrps;
243 for (i = 0; i < max_slots; ++
i) {
252 if (
WARN_ONCE(i == max_slots,
"Can't find any breakpoint slot"))
256 write_wb_reg(base, i, 0);
262 static int get_hbp_len(
u8 hbp_len)
264 unsigned int len_in_bytes = 0;
267 case ARM_BREAKPOINT_LEN_1:
270 case ARM_BREAKPOINT_LEN_2:
273 case ARM_BREAKPOINT_LEN_4:
276 case ARM_BREAKPOINT_LEN_8:
294 len = get_hbp_len(info->ctrl.
len);
305 int *gen_len,
int *gen_type)
309 case ARM_BREAKPOINT_EXECUTE:
312 case ARM_BREAKPOINT_LOAD:
315 case ARM_BREAKPOINT_STORE:
318 case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
327 case ARM_BREAKPOINT_LEN_1:
330 case ARM_BREAKPOINT_LEN_2:
333 case ARM_BREAKPOINT_LEN_4:
336 case ARM_BREAKPOINT_LEN_8:
349 static int arch_build_bp_info(
struct perf_event *bp)
354 switch (bp->
attr.bp_type) {
356 info->ctrl.
type = ARM_BREAKPOINT_EXECUTE;
359 info->ctrl.
type = ARM_BREAKPOINT_LOAD;
362 info->ctrl.
type = ARM_BREAKPOINT_STORE;
365 info->ctrl.
type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
372 switch (bp->
attr.bp_len) {
374 info->ctrl.
len = ARM_BREAKPOINT_LEN_1;
377 info->ctrl.
len = ARM_BREAKPOINT_LEN_2;
380 info->ctrl.
len = ARM_BREAKPOINT_LEN_4;
383 info->ctrl.
len = ARM_BREAKPOINT_LEN_8;
394 if (info->ctrl.
type == ARM_BREAKPOINT_EXECUTE) {
396 if (info->ctrl.
len != ARM_BREAKPOINT_LEN_2 &&
397 info->ctrl.
len != ARM_BREAKPOINT_LEN_4)
399 }
else if (info->ctrl.
len != ARM_BREAKPOINT_LEN_4) {
406 info->ctrl.
len = ARM_BREAKPOINT_LEN_4;
419 info->ctrl.privilege = AARCH64_BREAKPOINT_EL1;
421 info->ctrl.privilege = AARCH64_BREAKPOINT_EL0;
424 info->ctrl.enabled = !bp->
attr.disabled;
439 ret = arch_build_bp_info(bp);
453 if (info->ctrl.
len == ARM_BREAKPOINT_LEN_8)
454 alignment_mask = 0x7;
456 alignment_mask = 0x3;
457 offset = info->
address & alignment_mask;
464 if (info->ctrl.
len == ARM_BREAKPOINT_LEN_1)
468 if (info->ctrl.
len == ARM_BREAKPOINT_LEN_2)
474 info->
address &= ~alignment_mask;
477 if (info->ctrl.
type == ARM_BREAKPOINT_EXECUTE)
478 alignment_mask = 0x3;
480 alignment_mask = 0x7;
481 if (info->
address & alignment_mask)
489 if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.bp_target)
500 static void toggle_bp_registers(
int reg,
enum debug_el
el,
int enable)
502 int i, max_slots, privilege;
507 case AARCH64_DBG_REG_BCR:
509 max_slots = core_num_brps;
511 case AARCH64_DBG_REG_WCR:
513 max_slots = core_num_wrps;
519 for (i = 0; i < max_slots; ++
i) {
523 privilege = counter_arch_bp(slots[i])->ctrl.privilege;
524 if (debug_exception_level(privilege) != el)
527 ctrl = read_wb_reg(reg, i);
532 write_wb_reg(reg, i, ctrl);
539 static int breakpoint_handler(
unsigned long unused,
unsigned int esr,
542 int i,
step = 0, *kernel_step;
547 struct arch_hw_breakpoint_ctrl ctrl;
551 debug_info = &
current->thread.debug;
553 for (i = 0; i < core_num_brps; ++
i) {
562 val = read_wb_reg(AARCH64_DBG_REG_BVR, i);
563 if (val != (addr & ~0x3))
567 ctrl_reg = read_wb_reg(AARCH64_DBG_REG_BCR, i);
568 decode_ctrl_reg(ctrl_reg, &ctrl);
569 if (!((1 << (addr & 0x3)) & ctrl.len))
572 counter_arch_bp(bp)->trigger =
addr;
573 perf_bp_event(bp, regs);
576 if (!bp->overflow_handler)
586 debug_info->bps_disabled = 1;
587 toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 0);
590 if (debug_info->wps_disabled)
594 debug_info->suspended_step = 1;
598 toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 0);
601 if (*kernel_step != ARM_KERNEL_STEP_NONE)
605 *kernel_step = ARM_KERNEL_STEP_SUSPEND;
607 *kernel_step = ARM_KERNEL_STEP_ACTIVE;
615 static int watchpoint_handler(
unsigned long addr,
unsigned int esr,
618 int i, step = 0, *kernel_step,
access;
622 struct debug_info *debug_info;
624 struct arch_hw_breakpoint_ctrl ctrl;
627 debug_info = &
current->thread.debug;
629 for (i = 0; i < core_num_wrps; ++
i) {
637 info = counter_arch_bp(wp);
640 if (info->ctrl.
len == ARM_BREAKPOINT_LEN_8)
641 alignment_mask = 0x7;
643 alignment_mask = 0x3;
645 alignment_mask = 0x7;
649 val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
650 if (val != (addr & ~alignment_mask))
654 ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
655 decode_ctrl_reg(ctrl_reg, &ctrl);
656 if (!((1 << (addr & alignment_mask)) & ctrl.len))
665 if (!(access & hw_breakpoint_type(wp)))
668 info->trigger =
addr;
669 perf_bp_event(wp, regs);
672 if (!wp->overflow_handler)
686 toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 0);
689 debug_info->wps_disabled = 1;
692 if (debug_info->bps_disabled)
696 debug_info->suspended_step = 1;
700 toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 0);
703 if (*kernel_step != ARM_KERNEL_STEP_NONE)
707 *kernel_step = ARM_KERNEL_STEP_SUSPEND;
709 *kernel_step = ARM_KERNEL_STEP_ACTIVE;
722 struct debug_info *debug_info = &
current->thread.debug;
723 int handled_exception = 0, *kernel_step;
733 if (debug_info->bps_disabled) {
734 debug_info->bps_disabled = 0;
735 toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 1);
736 handled_exception = 1;
739 if (debug_info->wps_disabled) {
740 debug_info->wps_disabled = 0;
741 toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1);
742 handled_exception = 1;
745 if (handled_exception) {
746 if (debug_info->suspended_step) {
747 debug_info->suspended_step = 0;
749 handled_exception = 0;
754 }
else if (*kernel_step != ARM_KERNEL_STEP_NONE) {
755 toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1);
756 toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1);
758 if (!debug_info->wps_disabled)
759 toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1);
761 if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) {
763 handled_exception = 1;
765 handled_exception = 0;
768 *kernel_step = ARM_KERNEL_STEP_NONE;
771 return !handled_exception;
788 struct debug_info *current_debug_info, *next_debug_info;
790 current_debug_info = &
current->thread.debug;
791 next_debug_info = &next->
thread.debug;
794 if (current_debug_info->bps_disabled != next_debug_info->bps_disabled)
795 toggle_bp_registers(AARCH64_DBG_REG_BCR,
797 !next_debug_info->bps_disabled);
800 if (current_debug_info->wps_disabled != next_debug_info->wps_disabled)
801 toggle_bp_registers(AARCH64_DBG_REG_WCR,
803 !next_debug_info->wps_disabled);
809 static void reset_ctrl_regs(
void *unused)
813 for (i = 0; i < core_num_brps; ++
i) {
814 write_wb_reg(AARCH64_DBG_REG_BCR, i, 0
UL);
815 write_wb_reg(AARCH64_DBG_REG_BVR, i, 0
UL);
818 for (i = 0; i < core_num_wrps; ++
i) {
819 write_wb_reg(AARCH64_DBG_REG_WCR, i, 0
UL);
820 write_wb_reg(AARCH64_DBG_REG_WVR, i, 0
UL);
835 .notifier_call = hw_breakpoint_reset_notify,
841 static int __init arch_hw_breakpoint_init(
void)
843 core_num_brps = get_num_brps();
844 core_num_wrps = get_num_wrps();
846 pr_info(
"found %d breakpoint and %d watchpoint registers.\n",
847 core_num_brps, core_num_wrps);
854 reset_ctrl_regs(
NULL);
863 register_cpu_notifier(&hw_breakpoint_reset_nb);
877 unsigned long val,
void *
data)