aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-11-25 07:01:54 -0500
committerWill Deacon <will.deacon@arm.com>2010-12-06 06:55:56 -0500
commit6ee33c2712fcdff2568d9bbadb25c8e5a7c36212 (patch)
tree94c2510ccdd1cb2843897422746b67adf6ba1cd5 /arch/arm/kernel/hw_breakpoint.c
parent7d99331e4793b52d488e911876ef11d843c6c8c9 (diff)
ARM: hw_breakpoint: correct and simplify alignment fixup code
The current hw_breakpoint code tries to fix up the alignment of breakpoints so that we can make use of sparse byte-address-select bits in the control register and give the illusion that we can set breakpoints on unaligned addresses. Although this works on v6 cores, v7 forbids this behaviour, instead requiring breakpoints to be set on aligned addresses and have contiguous byte-address-select ranges depending on the instruction set in use. For ARM the only supported size is 4 bytes, whilst Thumb-2 also permits 2 byte breakpoints (watchpoints can be of 1, 2, 4 or 8 bytes long). This patch simplifies the alignment fixup code so that we require addresses to be aligned to the size of the corresponding breakpoint. This allows us to handle the common case of breaking on a half-word aligned Thumb-2 instruction and also allows us to set byte watchpoints on arbitrary addresses. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/hw_breakpoint.c')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c57
1 files changed, 31 insertions, 26 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 515a3c44c11..d37ed3501e5 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -537,6 +537,17 @@ static int arch_build_bp_info(struct perf_event *bp)
537 return -EINVAL; 537 return -EINVAL;
538 } 538 }
539 539
540 /*
541 * Breakpoints must be of length 2 (thumb) or 4 (ARM) bytes.
542 * Watchpoints can be of length 1, 2, 4 or 8 bytes if supported
543 * by the hardware and must be aligned to the appropriate number of
544 * bytes.
545 */
546 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE &&
547 info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
548 info->ctrl.len != ARM_BREAKPOINT_LEN_4)
549 return -EINVAL;
550
540 /* Address */ 551 /* Address */
541 info->address = bp->attr.bp_addr; 552 info->address = bp->attr.bp_addr;
542 553
@@ -561,7 +572,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
561{ 572{
562 struct arch_hw_breakpoint *info = counter_arch_bp(bp); 573 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
563 int ret = 0; 574 int ret = 0;
564 u32 bytelen, max_len, offset, alignment_mask = 0x3; 575 u32 offset, alignment_mask = 0x3;
565 576
566 /* Build the arch_hw_breakpoint. */ 577 /* Build the arch_hw_breakpoint. */
567 ret = arch_build_bp_info(bp); 578 ret = arch_build_bp_info(bp);
@@ -571,32 +582,27 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
571 /* Check address alignment. */ 582 /* Check address alignment. */
572 if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) 583 if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
573 alignment_mask = 0x7; 584 alignment_mask = 0x7;
574 if (info->address & alignment_mask) { 585 offset = info->address & alignment_mask;
575 /* 586 switch (offset) {
576 * Try to fix the alignment. This may result in a length 587 case 0:
577 * that is too large, so we must check for that. 588 /* Aligned */
578 */ 589 break;
579 bytelen = get_hbp_len(info->ctrl.len); 590 case 1:
580 max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 : 591 /* Allow single byte watchpoint. */
581 max_watchpoint_len; 592 if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
582 593 break;
583 if (max_len >= 8) 594 case 2:
584 offset = info->address & 0x7; 595 /* Allow halfword watchpoints and breakpoints. */
585 else 596 if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
586 offset = info->address & 0x3; 597 break;
587 598 default:
588 if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) { 599 ret = -EINVAL;
589 ret = -EFBIG; 600 goto out;
590 goto out;
591 }
592
593 info->ctrl.len <<= offset;
594 info->address &= ~offset;
595
596 pr_debug("breakpoint alignment fixup: length = 0x%x, "
597 "address = 0x%x\n", info->ctrl.len, info->address);
598 } 601 }
599 602
603 info->address &= ~alignment_mask;
604 info->ctrl.len <<= offset;
605
600 /* 606 /*
601 * Currently we rely on an overflow handler to take 607 * Currently we rely on an overflow handler to take
602 * care of single-stepping the breakpoint when it fires. 608 * care of single-stepping the breakpoint when it fires.
@@ -607,7 +613,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
607 (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()), 613 (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()),
608 "overflow handler required but none found")) { 614 "overflow handler required but none found")) {
609 ret = -EINVAL; 615 ret = -EINVAL;
610 goto out;
611 } 616 }
612out: 617out:
613 return ret; 618 return ret;