aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/hw_breakpoint.c')
-rw-r--r--arch/arm64/kernel/hw_breakpoint.c154
1 files changed, 116 insertions, 38 deletions
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index 367a954f9937..1c694f3c643c 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -36,6 +36,7 @@
36#include <asm/traps.h> 36#include <asm/traps.h>
37#include <asm/cputype.h> 37#include <asm/cputype.h>
38#include <asm/system_misc.h> 38#include <asm/system_misc.h>
39#include <asm/uaccess.h>
39 40
40/* Breakpoint currently in use for each BRP. */ 41/* Breakpoint currently in use for each BRP. */
41static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); 42static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
@@ -317,9 +318,21 @@ static int get_hbp_len(u8 hbp_len)
317 case ARM_BREAKPOINT_LEN_2: 318 case ARM_BREAKPOINT_LEN_2:
318 len_in_bytes = 2; 319 len_in_bytes = 2;
319 break; 320 break;
321 case ARM_BREAKPOINT_LEN_3:
322 len_in_bytes = 3;
323 break;
320 case ARM_BREAKPOINT_LEN_4: 324 case ARM_BREAKPOINT_LEN_4:
321 len_in_bytes = 4; 325 len_in_bytes = 4;
322 break; 326 break;
327 case ARM_BREAKPOINT_LEN_5:
328 len_in_bytes = 5;
329 break;
330 case ARM_BREAKPOINT_LEN_6:
331 len_in_bytes = 6;
332 break;
333 case ARM_BREAKPOINT_LEN_7:
334 len_in_bytes = 7;
335 break;
323 case ARM_BREAKPOINT_LEN_8: 336 case ARM_BREAKPOINT_LEN_8:
324 len_in_bytes = 8; 337 len_in_bytes = 8;
325 break; 338 break;
@@ -349,7 +362,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
349 * to generic breakpoint descriptions. 362 * to generic breakpoint descriptions.
350 */ 363 */
351int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, 364int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
352 int *gen_len, int *gen_type) 365 int *gen_len, int *gen_type, int *offset)
353{ 366{
354 /* Type */ 367 /* Type */
355 switch (ctrl.type) { 368 switch (ctrl.type) {
@@ -369,17 +382,33 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
369 return -EINVAL; 382 return -EINVAL;
370 } 383 }
371 384
385 if (!ctrl.len)
386 return -EINVAL;
387 *offset = __ffs(ctrl.len);
388
372 /* Len */ 389 /* Len */
373 switch (ctrl.len) { 390 switch (ctrl.len >> *offset) {
374 case ARM_BREAKPOINT_LEN_1: 391 case ARM_BREAKPOINT_LEN_1:
375 *gen_len = HW_BREAKPOINT_LEN_1; 392 *gen_len = HW_BREAKPOINT_LEN_1;
376 break; 393 break;
377 case ARM_BREAKPOINT_LEN_2: 394 case ARM_BREAKPOINT_LEN_2:
378 *gen_len = HW_BREAKPOINT_LEN_2; 395 *gen_len = HW_BREAKPOINT_LEN_2;
379 break; 396 break;
397 case ARM_BREAKPOINT_LEN_3:
398 *gen_len = HW_BREAKPOINT_LEN_3;
399 break;
380 case ARM_BREAKPOINT_LEN_4: 400 case ARM_BREAKPOINT_LEN_4:
381 *gen_len = HW_BREAKPOINT_LEN_4; 401 *gen_len = HW_BREAKPOINT_LEN_4;
382 break; 402 break;
403 case ARM_BREAKPOINT_LEN_5:
404 *gen_len = HW_BREAKPOINT_LEN_5;
405 break;
406 case ARM_BREAKPOINT_LEN_6:
407 *gen_len = HW_BREAKPOINT_LEN_6;
408 break;
409 case ARM_BREAKPOINT_LEN_7:
410 *gen_len = HW_BREAKPOINT_LEN_7;
411 break;
383 case ARM_BREAKPOINT_LEN_8: 412 case ARM_BREAKPOINT_LEN_8:
384 *gen_len = HW_BREAKPOINT_LEN_8; 413 *gen_len = HW_BREAKPOINT_LEN_8;
385 break; 414 break;
@@ -423,9 +452,21 @@ static int arch_build_bp_info(struct perf_event *bp)
423 case HW_BREAKPOINT_LEN_2: 452 case HW_BREAKPOINT_LEN_2:
424 info->ctrl.len = ARM_BREAKPOINT_LEN_2; 453 info->ctrl.len = ARM_BREAKPOINT_LEN_2;
425 break; 454 break;
455 case HW_BREAKPOINT_LEN_3:
456 info->ctrl.len = ARM_BREAKPOINT_LEN_3;
457 break;
426 case HW_BREAKPOINT_LEN_4: 458 case HW_BREAKPOINT_LEN_4:
427 info->ctrl.len = ARM_BREAKPOINT_LEN_4; 459 info->ctrl.len = ARM_BREAKPOINT_LEN_4;
428 break; 460 break;
461 case HW_BREAKPOINT_LEN_5:
462 info->ctrl.len = ARM_BREAKPOINT_LEN_5;
463 break;
464 case HW_BREAKPOINT_LEN_6:
465 info->ctrl.len = ARM_BREAKPOINT_LEN_6;
466 break;
467 case HW_BREAKPOINT_LEN_7:
468 info->ctrl.len = ARM_BREAKPOINT_LEN_7;
469 break;
429 case HW_BREAKPOINT_LEN_8: 470 case HW_BREAKPOINT_LEN_8:
430 info->ctrl.len = ARM_BREAKPOINT_LEN_8; 471 info->ctrl.len = ARM_BREAKPOINT_LEN_8;
431 break; 472 break;
@@ -517,18 +558,17 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
517 default: 558 default:
518 return -EINVAL; 559 return -EINVAL;
519 } 560 }
520
521 info->address &= ~alignment_mask;
522 info->ctrl.len <<= offset;
523 } else { 561 } else {
524 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) 562 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
525 alignment_mask = 0x3; 563 alignment_mask = 0x3;
526 else 564 else
527 alignment_mask = 0x7; 565 alignment_mask = 0x7;
528 if (info->address & alignment_mask) 566 offset = info->address & alignment_mask;
529 return -EINVAL;
530 } 567 }
531 568
569 info->address &= ~alignment_mask;
570 info->ctrl.len <<= offset;
571
532 /* 572 /*
533 * Disallow per-task kernel breakpoints since these would 573 * Disallow per-task kernel breakpoints since these would
534 * complicate the stepping code. 574 * complicate the stepping code.
@@ -661,12 +701,47 @@ unlock:
661} 701}
662NOKPROBE_SYMBOL(breakpoint_handler); 702NOKPROBE_SYMBOL(breakpoint_handler);
663 703
704/*
705 * Arm64 hardware does not always report a watchpoint hit address that matches
706 * one of the watchpoints set. It can also report an address "near" the
707 * watchpoint if a single instruction access both watched and unwatched
708 * addresses. There is no straight-forward way, short of disassembling the
709 * offending instruction, to map that address back to the watchpoint. This
710 * function computes the distance of the memory access from the watchpoint as a
711 * heuristic for the likelyhood that a given access triggered the watchpoint.
712 *
713 * See Section D2.10.5 "Determining the memory location that caused a Watchpoint
714 * exception" of ARMv8 Architecture Reference Manual for details.
715 *
716 * The function returns the distance of the address from the bytes watched by
717 * the watchpoint. In case of an exact match, it returns 0.
718 */
719static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
720 struct arch_hw_breakpoint_ctrl *ctrl)
721{
722 u64 wp_low, wp_high;
723 u32 lens, lene;
724
725 lens = __ffs(ctrl->len);
726 lene = __fls(ctrl->len);
727
728 wp_low = val + lens;
729 wp_high = val + lene;
730 if (addr < wp_low)
731 return wp_low - addr;
732 else if (addr > wp_high)
733 return addr - wp_high;
734 else
735 return 0;
736}
737
664static int watchpoint_handler(unsigned long addr, unsigned int esr, 738static int watchpoint_handler(unsigned long addr, unsigned int esr,
665 struct pt_regs *regs) 739 struct pt_regs *regs)
666{ 740{
667 int i, step = 0, *kernel_step, access; 741 int i, step = 0, *kernel_step, access, closest_match = 0;
742 u64 min_dist = -1, dist;
668 u32 ctrl_reg; 743 u32 ctrl_reg;
669 u64 val, alignment_mask; 744 u64 val;
670 struct perf_event *wp, **slots; 745 struct perf_event *wp, **slots;
671 struct debug_info *debug_info; 746 struct debug_info *debug_info;
672 struct arch_hw_breakpoint *info; 747 struct arch_hw_breakpoint *info;
@@ -675,35 +750,15 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
675 slots = this_cpu_ptr(wp_on_reg); 750 slots = this_cpu_ptr(wp_on_reg);
676 debug_info = &current->thread.debug; 751 debug_info = &current->thread.debug;
677 752
753 /*
754 * Find all watchpoints that match the reported address. If no exact
755 * match is found. Attribute the hit to the closest watchpoint.
756 */
757 rcu_read_lock();
678 for (i = 0; i < core_num_wrps; ++i) { 758 for (i = 0; i < core_num_wrps; ++i) {
679 rcu_read_lock();
680
681 wp = slots[i]; 759 wp = slots[i];
682
683 if (wp == NULL) 760 if (wp == NULL)
684 goto unlock; 761 continue;
685
686 info = counter_arch_bp(wp);
687 /* AArch32 watchpoints are either 4 or 8 bytes aligned. */
688 if (is_compat_task()) {
689 if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
690 alignment_mask = 0x7;
691 else
692 alignment_mask = 0x3;
693 } else {
694 alignment_mask = 0x7;
695 }
696
697 /* Check if the watchpoint value matches. */
698 val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
699 if (val != (addr & ~alignment_mask))
700 goto unlock;
701
702 /* Possible match, check the byte address select to confirm. */
703 ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
704 decode_ctrl_reg(ctrl_reg, &ctrl);
705 if (!((1 << (addr & alignment_mask)) & ctrl.len))
706 goto unlock;
707 762
708 /* 763 /*
709 * Check that the access type matches. 764 * Check that the access type matches.
@@ -712,18 +767,41 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
712 access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W : 767 access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
713 HW_BREAKPOINT_R; 768 HW_BREAKPOINT_R;
714 if (!(access & hw_breakpoint_type(wp))) 769 if (!(access & hw_breakpoint_type(wp)))
715 goto unlock; 770 continue;
716 771
772 /* Check if the watchpoint value and byte select match. */
773 val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
774 ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
775 decode_ctrl_reg(ctrl_reg, &ctrl);
776 dist = get_distance_from_watchpoint(addr, val, &ctrl);
777 if (dist < min_dist) {
778 min_dist = dist;
779 closest_match = i;
780 }
781 /* Is this an exact match? */
782 if (dist != 0)
783 continue;
784
785 info = counter_arch_bp(wp);
717 info->trigger = addr; 786 info->trigger = addr;
718 perf_bp_event(wp, regs); 787 perf_bp_event(wp, regs);
719 788
720 /* Do we need to handle the stepping? */ 789 /* Do we need to handle the stepping? */
721 if (!wp->overflow_handler) 790 if (!wp->overflow_handler)
722 step = 1; 791 step = 1;
792 }
793 if (min_dist > 0 && min_dist != -1) {
794 /* No exact match found. */
795 wp = slots[closest_match];
796 info = counter_arch_bp(wp);
797 info->trigger = addr;
798 perf_bp_event(wp, regs);
723 799
724unlock: 800 /* Do we need to handle the stepping? */
725 rcu_read_unlock(); 801 if (!wp->overflow_handler)
802 step = 1;
726 } 803 }
804 rcu_read_unlock();
727 805
728 if (!step) 806 if (!step)
729 return 0; 807 return 0;