Skip to contentSkip to conversation

ARM: add support for hw-breakpoints [v4]

PATCH New Will Deacon 3 participants 9 messages Jul 7, 2010 – Feb 16, 2011 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover ARM: add support for hw-breakpoints [v4]

This is version 4 of the patches originally posted at:

v1.) http://lists.infradead.org/pipermail/linux-arm-kernel/2010-February/009084.html
v2.) http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011170.html
v3.) http://lists.infradead.org/pipermail/linux-arm-kernel/2010-June/017680.html

Changes from v3 include:
- Based on 2.6.35-rc3
- Support for unaligned addresses
- Numerous bug fixes
- Tested with GDB, for which the testsuite passes

GDB patches have been posted here:

http://sourceware.org/ml/gdb-patches/2010-07/msg00110.html

I'd like to get these patches applied now that I'm confident that they function correctly, so please give them a go.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
Cc Matthew Gretton-Dann <[email protected]>

Will Deacon (4):
ARM: hw-breakpoint: add mechanism for hooking into prefetch aborts
ARM: hw-breakpoint: add ARM backend for the hw-breakpoint framework
ARM: hw-breakpoint: add new ptrace requests for hw-breakpoint
interaction
ARM: hw-breakpoint: add HAVE_HW_BREAKPOINT to Kconfig

 arch/arm/Kconfig                     |    1 +
 arch/arm/include/asm/hw_breakpoint.h |  117 ++++++
 arch/arm/include/asm/processor.h     |    4 +
 arch/arm/include/asm/ptrace.h        |    2 +
 arch/arm/include/asm/system.h        |    3 +
 arch/arm/kernel/Makefile             |    1 +
 arch/arm/kernel/hw_breakpoint.c      |  760 ++++++++++++++++++++++++++++++++++
 arch/arm/kernel/ptrace.c             |  223 ++++++++++
 arch/arm/mm/fault.c                  |   11 +
 9 files changed, 1122 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/hw_breakpoint.h
 create mode 100644 arch/arm/kernel/hw_breakpoint.c
#1 lore raw

PATCH 1/4 ARM: hw-breakpoint: add mechanism for hooking into prefetch aborts

On ARM processors with hardware breakpoint and watchpoint support, triggering these events results in a debug exception. These manifest as prefetch and data aborts respectively.

arch/arm/mm/fault.c already provides hook_fault_code for hooking into data aborts dependent on the DFSR. This patch adds a new function, hook_ifault_code for hooking into prefetch aborts in the same manner.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
---
 arch/arm/include/asm/system.h |    3 +++
 arch/arm/mm/fault.c           |   11 +++++++++++
 2 files changed, 14 insertions(+), 0 deletions(-)
arch/arm/include/asm/system.h +3 -0
index 5f4f480..42da2f8 100644
@@ -84,6 +84,9 @@ void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
 void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
 				       struct pt_regs *),
 		     int sig, const char *name);
+void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
+				       struct pt_regs *),
+		     int sig, const char *name);
 
 #define xchg(ptr,x) \
 	((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
arch/arm/mm/fault.c +11 -0
index cbfb2ed..fb7cbe7 100644
@@ -575,6 +575,17 @@ static struct fsr_info ifsr_info[] = {
 	{ do_bad,		SIGBUS,  0,		"unknown 31"			   },
 };
 
+void __init
+hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
+			int sig, const char *name)
+{
+	if (nr >= 0 && nr < ARRAY_SIZE(ifsr_info)) {
+		ifsr_info[nr].fn   = fn;
+		ifsr_info[nr].sig  = sig;
+		ifsr_info[nr].name = name;
+	}
+}
+
 asmlinkage void __exception
 do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
 {
Signature · 1 line
1.6.3.3
#2 lore raw

PATCH 2/4 ARM: hw-breakpoint: add ARM backend for the hw-breakpoint framework

The hw-breakpoint framework in the kernel requires architecture-specific support in order to install, remove, validate and manage hardware breakpoints.

This patch adds preliminary support for this framework to the ARM architecture, but restricts the number of watchpoints to a single resource to get around the fact that the Data Fault Address Register is unpredictable when a watchpoint debug exception is taken.

Currently, clients must handle synchronous breakpoint exceptions. This requires the ability to single-step over the causative instruction to avoid getting stuck in an infinite loop.

The memory-mapped extended debug interface is unsupported due to its unreliability in real implementations.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
---
 arch/arm/include/asm/hw_breakpoint.h |  117 ++++++
 arch/arm/kernel/hw_breakpoint.c      |  747 ++++++++++++++++++++++++++++++++++
 2 files changed, 864 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/hw_breakpoint.h
 create mode 100644 arch/arm/kernel/hw_breakpoint.c
arch/arm/include/asm/hw_breakpoint.h new file +117 -0
new file mode 100644
index 0000000..c995219
@@ -0,0 +1,117 @@
+#ifndef _ARM_HW_BREAKPOINT_H
+#define _ARM_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+struct arch_hw_breakpoint_ctrl {
+		u32 __reserved	: 19,
+		len		: 8,
+		type		: 2,
+		privilege	: 2,
+		enabled		: 1;
+};
+
+struct arch_hw_breakpoint {
+	u32	address;
+	u32	trigger;
+	struct arch_hw_breakpoint_ctrl ctrl;
+};
+
+static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
+{
+	return (ctrl.len << 5) | (ctrl.type << 3) |
+		(ctrl.privilege << 1) | ctrl.enabled;
+}
+
+static inline void decode_ctrl_reg(u32 reg,
+				   struct arch_hw_breakpoint_ctrl *ctrl)
+{
+	ctrl->enabled	= reg & 0x1;
+	reg >>= 1;
+	ctrl->privilege	= reg & 0x3;
+	reg >>= 2;
+	ctrl->type	= reg & 0x3;
+	reg >>= 2;
+	ctrl->len	= reg & 0xff;
+}
+
+/* Debug architecture numbers. */
+#define ARM_DEBUG_ARCH_V6	1
+#define ARM_DEBUG_ARCH_V6_1	2
+#define ARM_DEBUG_ARCH_V7_ECP14	3
+#define ARM_DEBUG_ARCH_V7_MM	4
+
+/* Breakpoint */
+#define ARM_BREAKPOINT_EXECUTE	0
+
+/* Watchpoints */
+#define ARM_BREAKPOINT_LOAD	1
+#define ARM_BREAKPOINT_STORE	2
+
+/* Privilege Levels */
+#define ARM_BREAKPOINT_PRIV	1
+#define ARM_BREAKPOINT_USER	2
+
+/* Lengths */
+#define ARM_BREAKPOINT_LEN_1	0x1
+#define ARM_BREAKPOINT_LEN_2	0x3
+#define ARM_BREAKPOINT_LEN_4	0xf
+#define ARM_BREAKPOINT_LEN_8	0xff
+
+/* Limits */
+#define ARM_MAX_BRP		16
+#define ARM_MAX_WRP		16
+#define ARM_MAX_HBP_SLOTS	(ARM_MAX_BRP + ARM_MAX_WRP)
+
+/* DSCR method of entry bits. */
+#define ARM_DSCR_MOE(x)			((x >> 2) & 0xf)
+#define ARM_ENTRY_BREAKPOINT		0x1
+#define ARM_ENTRY_ASYNC_WATCHPOINT	0x2
+#define ARM_ENTRY_SYNC_WATCHPOINT	0xa
+
+/* DSCR monitor/halting bits. */
+#define ARM_DSCR_HDBGEN		(1 << 14)
+#define ARM_DSCR_MDBGEN		(1 << 15)
+
+/* opcode2 numbers for the co-processor instructions. */
+#define ARM_OP2_BVR		4
+#define ARM_OP2_BCR		5
+#define ARM_OP2_WVR		6
+#define ARM_OP2_WCR		7
+
+/* Base register numbers for the debug registers. */
+#define ARM_BASE_BVR		64
+#define ARM_BASE_BCR		80
+#define ARM_BASE_WVR		96
+#define ARM_BASE_WCR		112
+
+/* Accessor macros for the debug registers. */
+#define ARM_DBG_READ(M, OP2, VAL) do {\
+	asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
+} while (0)
+
+#define ARM_DBG_WRITE(M, OP2, VAL) do {\
+	asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
+} while (0)
+
+struct notifier_block;
+struct perf_event;
+struct pmu;
+struct task_struct;
+
+extern struct pmu perf_ops_bp;
+extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+				  int *gen_len, int *gen_type);
+extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+					   unsigned long val, void *data);
+extern u8 arch_get_debug_arch(void);
+extern u8 arch_get_max_wp_len(void);
+
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+int hw_breakpoint_slots(int type);
+
+#endif	/* __KERNEL__ */
+#endif	/* _ARM_HW_BREAKPOINT_H */
arch/arm/kernel/hw_breakpoint.c new file +747 -0

747 lines not on this page · raw message

Signature · 1 line
1.6.3.3
#3 lore raw

PATCH 3/4 ARM: hw-breakpoint: add new ptrace requests for hw-breakpoint interaction

For debuggers to take advantage of the hw-breakpoint framework in the kernel, it is necessary to expose the API calls via a ptrace interface.

This patch exposes the hardware breakpoints framework as a collection of virtual registers, accesible using PTRACE_SETHBPREGS and PTRACE_GETHBPREGS requests. The breakpoints are stored in the debug_info struct of the running thread.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
---
 arch/arm/include/asm/processor.h |    4 +
 arch/arm/include/asm/ptrace.h    |    2 +
 arch/arm/kernel/hw_breakpoint.c  |   13 +++
 arch/arm/kernel/ptrace.c         |  223 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 242 insertions(+), 0 deletions(-)
arch/arm/include/asm/processor.h +4 -0
index 6a89567..dbd33c3 100644
@@ -19,6 +19,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
@@ -41,6 +42,9 @@ struct debug_entry {
 struct debug_info {
 	int			nsaved;
 	struct debug_entry	bp[2];
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	struct perf_event	*hbp[ARM_MAX_HBP_SLOTS];
+#endif
 };
 
 struct thread_struct {
arch/arm/include/asm/ptrace.h +2 -0
index 9dcb11e..21560e4 100644
@@ -29,6 +29,8 @@
 #define PTRACE_SETCRUNCHREGS	26
 #define PTRACE_GETVFPREGS	27
 #define PTRACE_SETVFPREGS	28
+#define PTRACE_GETHBPREGS	29
+#define PTRACE_SETHBPREGS	30
 
 /*
  * PSR bits
arch/arm/kernel/hw_breakpoint.c +13 -0
index ab13e33..f251558 100644
@@ -673,6 +673,19 @@ out:
 	return ret;
 }
 
+static int hw_breakpoint_thread_notify(struct notifier_block *self,
+				       unsigned long cmd, void *t)
+{
+	if (cmd == THREAD_NOTIFY_FLUSH)
+		flush_ptrace_hw_breakpoint(current);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block hw_breakpoint_thread_notifier_block = {
+	.notifier_call = hw_breakpoint_thread_notify,
+};
+
 /*
  * One-time initialisation.
  */
arch/arm/kernel/ptrace.c +223 -0

241 lines not on this page · raw message

Signature · 1 line
1.6.3.3
#4 lore raw

PATCH 4/4 ARM: hw-breakpoint: add HAVE_HW_BREAKPOINT to Kconfig

If we're targetting a v6 or v7 core and have at least software perf events available, then automatically add support for hardware breakpoints.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
---
 arch/arm/Kconfig         |    1 +
 arch/arm/kernel/Makefile |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/Kconfig +1 -0
index e57cb24..7ed4d58 100644
@@ -24,6 +24,7 @@ config ARM
 	select HAVE_KERNEL_LZMA
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
+	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
arch/arm/kernel/Makefile +1 -0
index 26d302c..e679fb0 100644
@@ -39,6 +39,7 @@ obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_ARM_UNWIND)	+= unwind.o
 obj-$(CONFIG_HAVE_TCM)		+= tcm.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
Signature · 1 line
1.6.3.3
#5 lore raw

cover ARM: add support for hw-breakpoints [v4]

In reply to Will Deacon

Hello,

Quoted 14 lines

This is version 4 of the patches originally posted at:

v1.) http://lists.infradead.org/pipermail/linux-arm-kernel/2010-February/009084.html
v2.) http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011170.html
v3.) http://lists.infradead.org/pipermail/linux-arm-kernel/2010-June/017680.html

Changes from v3 include:
- Based on 2.6.35-rc3
- Support for unaligned addresses
- Numerous bug fixes
- Tested with GDB, for which the testsuite passes

GDB patches have been posted here:

Quoted 9 lines

http://sourceware.org/ml/gdb-patches/2010-07/msg00110.html

I'd like to get these patches applied now that I'm confident that they function correctly, so please give them a go.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
Cc Matthew Gretton-Dann <[email protected]>

I accidentally passed suppress-cc=all to git send-email, so this is a pointer for the people I meant to CC. If you want to view the patchset it's archived at:

http://lists.infradead.org/pipermail/linux-arm-kernel/2010-July/019882.html

Sorry about that,

Will

A message that is not in the archive (sent off-list or not yet received): -857909442890734186@unknownmsgid

#7 lore raw

cover ARM: add support for hw-breakpoints [v4]

There seems to be a bug in the gdb patch... There should probably be a separate loop for wpts.

      for (i = 0; i < info->bp_count; i++)
Quoted 6 lines
	{
	  if (arm_hwbp_control_is_enabled (p->bpts[i].control))
	    arm_linux_insert_hw_breakpoint1 (p->bpts + i, tid, 0);
	  if (arm_hwbp_control_is_enabled (p->wpts[i].control))
	    arm_linux_insert_hw_breakpoint1 (p->wpts + i, tid, 1);
	}

-Karthik

Quoted 41 lines · Will Deacon

Hello,

Quoted 3 lines

This is version 4 of the patches originally posted at:

v1.)

http://lists.infradead.org/pipermail/linux-arm-kernel/2010-February/009084.html

Quoted 1 line

v2.)

http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011170.html

Quoted 1 line

v3.)

http://lists.infradead.org/pipermail/linux-arm-kernel/2010-June/017680.html

Quoted 9 lines

Changes from v3 include:
- Based on 2.6.35-rc3
- Support for unaligned addresses
- Numerous bug fixes
- Tested with GDB, for which the testsuite passes

GDB patches have been posted here:

Quoted 9 lines

http://sourceware.org/ml/gdb-patches/2010-07/msg00110.html

I'd like to get these patches applied now that I'm confident that they function correctly, so please give them a go.

Cc Frederic Weisbecker <[email protected]>
Cc S. Karthikeyan <[email protected]>
Cc Matthew Gretton-Dann <[email protected]>

I accidentally passed suppress-cc=all to git send-email, so this is a pointer for the people I meant to CC. If you want to view the patchset it's archived at:

http://lists.infradead.org/pipermail/linux-arm-kernel/2010-July/019882.html

Sorry about that,

Will

Signature · 6 lines
---
S. Karthikeyan | +919980814745
---
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110216/8ec27222/attachment-0001.html>
#8 lore raw

cover ARM: add support for hw-breakpoints [v4]

Hi Karthik,

Quoted 9 lines

There seems to be a bug in the gdb patch... There should probably be a separate loop for wpts.

      for (i = 0; i < info->bp_count; i++)
Quoted 6 lines
	{
	  if (arm_hwbp_control_is_enabled (p->bpts[i].control))
	    arm_linux_insert_hw_breakpoint1 (p->bpts + i, tid, 0);
	  if (arm_hwbp_control_is_enabled (p->wpts[i].control))
	    arm_linux_insert_hw_breakpoint1 (p->wpts + i, tid, 1);
	}

Ulrich Weigand (added to CC) is dealing with the GDB patches, so he will have more idea about this than me. Last I heard, the testsuite was passing so I guess this has been fixed if it was a problem.

Cheers,

Will

#9 lore raw

cover ARM: add support for hw-breakpoints [v4]

"Will Deacon" <[email protected]> wrote on 02/16/2011 12:59:49 PM:

Quoted 11 lines
Quoted 1 line

There seems to be a bug in the gdb patch... There should probably

be a separate loop for wpts.

Quoted 8 lines
      for (i = 0; i < info->bp_count; i++)
Quoted 6 lines
   {
     if (arm_hwbp_control_is_enabled (p->bpts[i].control))
       arm_linux_insert_hw_breakpoint1 (p->bpts + i, tid, 0);
     if (arm_hwbp_control_is_enabled (p->wpts[i].control))
       arm_linux_insert_hw_breakpoint1 (p->wpts + i, tid, 1);
   }
Quoted 3 lines

Ulrich Weigand (added to CC) is dealing with the GDB patches, so he will have more idea about this than me. Last I heard, the testsuite was passing so I guess this has been fixed if it was a problem.

Yes, this is indeed a bug (it only occurs sporadically, since its effect is to access random memory), and it should be fixed by using two separate loops.

That's one of the changes I've had to make as well. I'll post an updated patch set including all the changes required to get a clean testsuite run shortly ...

Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
Dr. Ulrich Weigand | Phone: +49-7031/16-3727
STSM, GNU compiler and toolchain for Linux on System z and Cell/B.E. IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter | Gesch?ftsf?hrung: Dirk
Wittkopp
Sitz der Gesellschaft: B?blingen | Registergericht: Amtsgericht
Stuttgart, HRB 243294