diff mbox

[3/4] arm64: Allow hw watchpoint of length 3,5,6 and 7

Message ID d6ebb3e9776154da4c1a41f17446e9e31c891a7d.1476251587.git.panand@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pratyush Anand Oct. 12, 2016, 5:58 a.m. UTC
Since, arm64 can support all offset within a double word limit. Therefore,
now support other lengths within that range as well.

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
 arch/arm64/include/asm/hw_breakpoint.h |  4 ++++
 arch/arm64/kernel/hw_breakpoint.c      | 36 ++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

Comments

Yao Qi Oct. 12, 2016, 11:16 a.m. UTC | #1
On Wed, Oct 12, 2016 at 6:58 AM, Pratyush Anand <panand@redhat.com> wrote:
> Since, arm64 can support all offset within a double word limit. Therefore,
> now support other lengths within that range as well.

How does ptracer (like GDB) detect kernel has already supported all byte
address select values?  I suppose ptrace(NT_ARM_HW_WATCH, ) with
len is 3 or 5 fail on current kernel but is of success after your patches
applied.

GDB is aware of the byte address select limitation in kernel, so it always
sets 1,2,4,8 in len in ctrl.  GDB needs to know whether the limitation is still
there or not.
Pratyush Anand Oct. 13, 2016, 10:22 a.m. UTC | #2
On Wednesday 12 October 2016 04:46 PM, Yao Qi wrote:
> On Wed, Oct 12, 2016 at 6:58 AM, Pratyush Anand <panand@redhat.com> wrote:
>> Since, arm64 can support all offset within a double word limit. Therefore,
>> now support other lengths within that range as well.
>
> How does ptracer (like GDB) detect kernel has already supported all byte
> address select values?  I suppose ptrace(NT_ARM_HW_WATCH, ) with
> len is 3 or 5 fail on current kernel but is of success after your patches
> applied.
>

Thanks for testing these patches.

I do not know if we can know that other than the failure of 
ptrace(PTRACE_SETREGSET, .., NT_ARM_HW_WATCH, ..). I do not see any such 
option in `man ptrace`.


> GDB is aware of the byte address select limitation in kernel, so it always
> sets 1,2,4,8 in len in ctrl.  GDB needs to know whether the limitation is still
> there or not.
>

Not sure if other than "kernel version" anything will help here.

~Pratyush
Pavel Labath Oct. 13, 2016, 2:29 p.m. UTC | #3
On 13 October 2016 at 11:22, Pratyush Anand <panand@redhat.com> wrote:
>
>
> On Wednesday 12 October 2016 04:46 PM, Yao Qi wrote:
>>
>> On Wed, Oct 12, 2016 at 6:58 AM, Pratyush Anand <panand@redhat.com> wrote:
>>>
>>> Since, arm64 can support all offset within a double word limit.
>>> Therefore,
>>> now support other lengths within that range as well.
>>
>>
>> How does ptracer (like GDB) detect kernel has already supported all byte
>> address select values?  I suppose ptrace(NT_ARM_HW_WATCH, ) with
>> len is 3 or 5 fail on current kernel but is of success after your patches
>> applied.
>>
>
> Thanks for testing these patches.
>
> I do not know if we can know that other than the failure of
> ptrace(PTRACE_SETREGSET, .., NT_ARM_HW_WATCH, ..). I do not see any such
> option in `man ptrace`.
That's how I intend to implement support for this in LLDB.
if (setExactWatchpoint())
  return true; // watchpoint set, new kernel
if (setApproxWatchpoint())
  return true; // watchpoint set, old kernel
return false; // watchpoints not working

seems straight-forward enough to me.
diff mbox

Patch

diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
index 4f4e58bee9bc..7a18c8520588 100644
--- a/arch/arm64/include/asm/hw_breakpoint.h
+++ b/arch/arm64/include/asm/hw_breakpoint.h
@@ -76,7 +76,11 @@  static inline void decode_ctrl_reg(u32 reg,
 /* Lengths */
 #define ARM_BREAKPOINT_LEN_1	0x1
 #define ARM_BREAKPOINT_LEN_2	0x3
+#define ARM_BREAKPOINT_LEN_3	0x7
 #define ARM_BREAKPOINT_LEN_4	0xf
+#define ARM_BREAKPOINT_LEN_5	0x1f
+#define ARM_BREAKPOINT_LEN_6	0x3f
+#define ARM_BREAKPOINT_LEN_7	0x7f
 #define ARM_BREAKPOINT_LEN_8	0xff
 
 /* Kernel stepping */
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index c888c23149ad..7ff2c3cfeb46 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -317,9 +317,21 @@  static int get_hbp_len(u8 hbp_len)
 	case ARM_BREAKPOINT_LEN_2:
 		len_in_bytes = 2;
 		break;
+	case ARM_BREAKPOINT_LEN_3:
+		len_in_bytes = 3;
+		break;
 	case ARM_BREAKPOINT_LEN_4:
 		len_in_bytes = 4;
 		break;
+	case ARM_BREAKPOINT_LEN_5:
+		len_in_bytes = 5;
+		break;
+	case ARM_BREAKPOINT_LEN_6:
+		len_in_bytes = 6;
+		break;
+	case ARM_BREAKPOINT_LEN_7:
+		len_in_bytes = 7;
+		break;
 	case ARM_BREAKPOINT_LEN_8:
 		len_in_bytes = 8;
 		break;
@@ -379,9 +391,21 @@  int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
 	case ARM_BREAKPOINT_LEN_2:
 		*gen_len = HW_BREAKPOINT_LEN_2;
 		break;
+	case ARM_BREAKPOINT_LEN_3:
+		*gen_len = HW_BREAKPOINT_LEN_3;
+		break;
 	case ARM_BREAKPOINT_LEN_4:
 		*gen_len = HW_BREAKPOINT_LEN_4;
 		break;
+	case ARM_BREAKPOINT_LEN_5:
+		*gen_len = HW_BREAKPOINT_LEN_5;
+		break;
+	case ARM_BREAKPOINT_LEN_6:
+		*gen_len = HW_BREAKPOINT_LEN_6;
+		break;
+	case ARM_BREAKPOINT_LEN_7:
+		*gen_len = HW_BREAKPOINT_LEN_7;
+		break;
 	case ARM_BREAKPOINT_LEN_8:
 		*gen_len = HW_BREAKPOINT_LEN_8;
 		break;
@@ -425,9 +449,21 @@  static int arch_build_bp_info(struct perf_event *bp)
 	case HW_BREAKPOINT_LEN_2:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_2;
 		break;
+	case HW_BREAKPOINT_LEN_3:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_3;
+		break;
 	case HW_BREAKPOINT_LEN_4:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_4;
 		break;
+	case HW_BREAKPOINT_LEN_5:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_5;
+		break;
+	case HW_BREAKPOINT_LEN_6:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_6;
+		break;
+	case HW_BREAKPOINT_LEN_7:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_7;
+		break;
 	case HW_BREAKPOINT_LEN_8:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_8;
 		break;