Skip to contentSkip to conversation

powerpc: add POWER8 DAWR support

PATCH New Michael Neuling 2 participants 12 messages Dec 21, 2012 – Jan 22, 2014 1 message not in the archive

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

cover powerpc: add POWER8 DAWR support

Add support for the Data Address Watchpoint Register (DAWR) as found in POWER8. This replaces the DABR found in POWER7 and earlier and allows for wider watchpoint areas.

Signature · 1 line
1.7.10.4
#1 lore raw

PATCH 1/7 powerpc: Remove extra zeros from 32 bit CPU features definitions

These are 32 bit, so no need to have a bunch of wasted 0s.

The 0s saved here can be put to better use elsewhere, like at the end of my pay check.

---
 arch/powerpc/include/asm/cputable.h |   62 +++++++++++++++++------------------
 1 file changed, 31 insertions(+), 31 deletions(-)
arch/powerpc/include/asm/cputable.h +31 -31
index cbbec56a..0a4c67d 100644
@@ -106,37 +106,37 @@ extern const char *powerpc_base_platform;
 /* CPU kernel features */
 
 /* Retain the 32b definitions all use bottom half of word */
-#define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x0000000000000001)
-#define CPU_FTR_L2CR			ASM_CONST(0x0000000000000002)
-#define CPU_FTR_SPEC7450		ASM_CONST(0x0000000000000004)
-#define CPU_FTR_ALTIVEC			ASM_CONST(0x0000000000000008)
-#define CPU_FTR_TAU			ASM_CONST(0x0000000000000010)
-#define CPU_FTR_CAN_DOZE		ASM_CONST(0x0000000000000020)
-#define CPU_FTR_USE_TB			ASM_CONST(0x0000000000000040)
-#define CPU_FTR_L2CSR			ASM_CONST(0x0000000000000080)
-#define CPU_FTR_601			ASM_CONST(0x0000000000000100)
-#define CPU_FTR_DBELL			ASM_CONST(0x0000000000000200)
-#define CPU_FTR_CAN_NAP			ASM_CONST(0x0000000000000400)
-#define CPU_FTR_L3CR			ASM_CONST(0x0000000000000800)
-#define CPU_FTR_L3_DISABLE_NAP		ASM_CONST(0x0000000000001000)
-#define CPU_FTR_NAP_DISABLE_L2_PR	ASM_CONST(0x0000000000002000)
-#define CPU_FTR_DUAL_PLL_750FX		ASM_CONST(0x0000000000004000)
-#define CPU_FTR_NO_DPM			ASM_CONST(0x0000000000008000)
-#define CPU_FTR_476_DD2			ASM_CONST(0x0000000000010000)
-#define CPU_FTR_NEED_COHERENT		ASM_CONST(0x0000000000020000)
-#define CPU_FTR_NO_BTIC			ASM_CONST(0x0000000000040000)
-#define CPU_FTR_DEBUG_LVL_EXC		ASM_CONST(0x0000000000080000)
-#define CPU_FTR_NODSISRALIGN		ASM_CONST(0x0000000000100000)
-#define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
-#define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
-#define CPU_FTR_FPU_UNAVAILABLE		ASM_CONST(0x0000000000800000)
-#define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x0000000001000000)
-#define CPU_FTR_SPE			ASM_CONST(0x0000000002000000)
-#define CPU_FTR_NEED_PAIRED_STWCX	ASM_CONST(0x0000000004000000)
-#define CPU_FTR_LWSYNC			ASM_CONST(0x0000000008000000)
-#define CPU_FTR_NOEXECUTE		ASM_CONST(0x0000000010000000)
-#define CPU_FTR_INDEXED_DCR		ASM_CONST(0x0000000020000000)
-#define CPU_FTR_EMB_HV			ASM_CONST(0x0000000040000000)
+#define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x00000001)
+#define CPU_FTR_L2CR			ASM_CONST(0x00000002)
+#define CPU_FTR_SPEC7450		ASM_CONST(0x00000004)
+#define CPU_FTR_ALTIVEC			ASM_CONST(0x00000008)
+#define CPU_FTR_TAU			ASM_CONST(0x00000010)
+#define CPU_FTR_CAN_DOZE		ASM_CONST(0x00000020)
+#define CPU_FTR_USE_TB			ASM_CONST(0x00000040)
+#define CPU_FTR_L2CSR			ASM_CONST(0x00000080)
+#define CPU_FTR_601			ASM_CONST(0x00000100)
+#define CPU_FTR_DBELL			ASM_CONST(0x00000200)
+#define CPU_FTR_CAN_NAP			ASM_CONST(0x00000400)
+#define CPU_FTR_L3CR			ASM_CONST(0x00000800)
+#define CPU_FTR_L3_DISABLE_NAP		ASM_CONST(0x00001000)
+#define CPU_FTR_NAP_DISABLE_L2_PR	ASM_CONST(0x00002000)
+#define CPU_FTR_DUAL_PLL_750FX		ASM_CONST(0x00004000)
+#define CPU_FTR_NO_DPM			ASM_CONST(0x00008000)
+#define CPU_FTR_476_DD2			ASM_CONST(0x00010000)
+#define CPU_FTR_NEED_COHERENT		ASM_CONST(0x00020000)
+#define CPU_FTR_NO_BTIC			ASM_CONST(0x00040000)
+#define CPU_FTR_DEBUG_LVL_EXC		ASM_CONST(0x00080000)
+#define CPU_FTR_NODSISRALIGN		ASM_CONST(0x00100000)
+#define CPU_FTR_PPC_LE			ASM_CONST(0x00200000)
+#define CPU_FTR_REAL_LE			ASM_CONST(0x00400000)
+#define CPU_FTR_FPU_UNAVAILABLE		ASM_CONST(0x00800000)
+#define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x01000000)
+#define CPU_FTR_SPE			ASM_CONST(0x02000000)
+#define CPU_FTR_NEED_PAIRED_STWCX	ASM_CONST(0x04000000)
+#define CPU_FTR_LWSYNC			ASM_CONST(0x08000000)
+#define CPU_FTR_NOEXECUTE		ASM_CONST(0x10000000)
+#define CPU_FTR_INDEXED_DCR		ASM_CONST(0x20000000)
+#define CPU_FTR_EMB_HV			ASM_CONST(0x40000000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
Signature · 1 line
1.7.10.4
#2 lore raw

PATCH 2/7 powerpc: Repack 64bit CPU features to remove holes

In reply to Michael Neuling

This frees up 7 bits for crazy new CPU features.

---
 arch/powerpc/include/asm/cputable.h |   50 +++++++++++++++++------------------
 1 file changed, 25 insertions(+), 25 deletions(-)
arch/powerpc/include/asm/cputable.h +25 -25
index 0a4c67d..d1f5911 100644
@@ -148,31 +148,31 @@ extern const char *powerpc_base_platform;
 #define LONG_ASM_CONST(x)		0
 #endif
 
-#define CPU_FTR_HVMODE			LONG_ASM_CONST(0x0000000200000000)
-#define CPU_FTR_ARCH_201		LONG_ASM_CONST(0x0000000400000000)
-#define CPU_FTR_ARCH_206		LONG_ASM_CONST(0x0000000800000000)
-#define CPU_FTR_CFAR			LONG_ASM_CONST(0x0000001000000000)
-#define CPU_FTR_IABR			LONG_ASM_CONST(0x0000002000000000)
-#define CPU_FTR_MMCRA			LONG_ASM_CONST(0x0000004000000000)
-#define CPU_FTR_CTRL			LONG_ASM_CONST(0x0000008000000000)
-#define CPU_FTR_SMT			LONG_ASM_CONST(0x0000010000000000)
-#define CPU_FTR_PAUSE_ZERO		LONG_ASM_CONST(0x0000200000000000)
-#define CPU_FTR_PURR			LONG_ASM_CONST(0x0000400000000000)
-#define CPU_FTR_CELL_TB_BUG		LONG_ASM_CONST(0x0000800000000000)
-#define CPU_FTR_SPURR			LONG_ASM_CONST(0x0001000000000000)
-#define CPU_FTR_DSCR			LONG_ASM_CONST(0x0002000000000000)
-#define CPU_FTR_VSX			LONG_ASM_CONST(0x0010000000000000)
-#define CPU_FTR_SAO			LONG_ASM_CONST(0x0020000000000000)
-#define CPU_FTR_CP_USE_DCBTZ		LONG_ASM_CONST(0x0040000000000000)
-#define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0080000000000000)
-#define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0100000000000000)
-#define CPU_FTR_STCX_CHECKS_ADDRESS	LONG_ASM_CONST(0x0200000000000000)
-#define CPU_FTR_POPCNTB			LONG_ASM_CONST(0x0400000000000000)
-#define CPU_FTR_POPCNTD			LONG_ASM_CONST(0x0800000000000000)
-#define CPU_FTR_ICSWX			LONG_ASM_CONST(0x1000000000000000)
-#define CPU_FTR_VMX_COPY		LONG_ASM_CONST(0x2000000000000000)
-#define CPU_FTR_TM			LONG_ASM_CONST(0x4000000000000000)
-#define CPU_FTR_BCTAR			LONG_ASM_CONST(0x8000000000000000)
+#define CPU_FTR_HVMODE			LONG_ASM_CONST(0x0000000100000000)
+#define CPU_FTR_ARCH_201		LONG_ASM_CONST(0x0000000200000000)
+#define CPU_FTR_ARCH_206		LONG_ASM_CONST(0x0000000400000000)
+#define CPU_FTR_CFAR			LONG_ASM_CONST(0x0000000800000000)
+#define CPU_FTR_IABR			LONG_ASM_CONST(0x0000001000000000)
+#define CPU_FTR_MMCRA			LONG_ASM_CONST(0x0000002000000000)
+#define CPU_FTR_CTRL			LONG_ASM_CONST(0x0000004000000000)
+#define CPU_FTR_SMT			LONG_ASM_CONST(0x0000008000000000)
+#define CPU_FTR_PAUSE_ZERO		LONG_ASM_CONST(0x0000010000000000)
+#define CPU_FTR_PURR			LONG_ASM_CONST(0x0000020000000000)
+#define CPU_FTR_CELL_TB_BUG		LONG_ASM_CONST(0x0000040000000000)
+#define CPU_FTR_SPURR			LONG_ASM_CONST(0x0000080000000000)
+#define CPU_FTR_DSCR			LONG_ASM_CONST(0x0000100000000000)
+#define CPU_FTR_VSX			LONG_ASM_CONST(0x0000200000000000)
+#define CPU_FTR_SAO			LONG_ASM_CONST(0x0000400000000000)
+#define CPU_FTR_CP_USE_DCBTZ		LONG_ASM_CONST(0x0000800000000000)
+#define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0001000000000000)
+#define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0002000000000000)
+#define CPU_FTR_STCX_CHECKS_ADDRESS	LONG_ASM_CONST(0x0004000000000000)
+#define CPU_FTR_POPCNTB			LONG_ASM_CONST(0x0008000000000000)
+#define CPU_FTR_POPCNTD			LONG_ASM_CONST(0x0010000000000000)
+#define CPU_FTR_ICSWX			LONG_ASM_CONST(0x0020000000000000)
+#define CPU_FTR_VMX_COPY		LONG_ASM_CONST(0x0040000000000000)
+#define CPU_FTR_TM			LONG_ASM_CONST(0x0080000000000000)
+#define CPU_FTR_BCTAR			LONG_ASM_CONST(0x0100000000000000)
 
 #ifndef __ASSEMBLY__
 
Signature · 1 line
1.7.10.4
#3 lore raw

PATCH 3/7 powerpc: Add helper functions set the DAWR and CIABR using set_mode

In reply to Michael Neuling

From: Ian Munsie <[email protected]>

These are just wrappers around the new set_mode HCALL.

---
 arch/powerpc/platforms/pseries/plpar_wrappers.h |   10 ++++++++++
 1 file changed, 10 insertions(+)
arch/powerpc/platforms/pseries/plpar_wrappers.h +10 -0
index e6cc34a..fd09183 100644
@@ -304,4 +304,14 @@ static inline long disable_reloc_on_exceptions(void) {
 	return plpar_set_mode(0, 3, 0, 0);
 }
 
+static inline long plapr_set_ciabr(unsigned long ciabr)
+{
+	return plpar_set_mode(0, 1, ciabr, 0);
+}
+
+static inline long plapr_set_watchpoint0(unsigned long dawr0, unsigned long dawrx0)
+{
+	return plpar_set_mode(0, 2, dawr0, dawrx0);
+}
+
 #endif /* _PSERIES_PLPAR_WRAPPERS_H */
Signature · 1 line
1.7.10.4
#4 lore raw

PATCH 4/7 powerpc: Add DAWR CPU feature bit definition

In reply to Michael Neuling

.. and add it to POWER8 cpu features.

---
 arch/powerpc/include/asm/cputable.h |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/include/asm/cputable.h +2 -1
index d1f5911..2134e26 100644
@@ -173,6 +173,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_VMX_COPY		LONG_ASM_CONST(0x0040000000000000)
 #define CPU_FTR_TM			LONG_ASM_CONST(0x0080000000000000)
 #define CPU_FTR_BCTAR			LONG_ASM_CONST(0x0100000000000000)
+#define CPU_FTR_DAWR			LONG_ASM_CONST(0x0200000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -418,7 +419,7 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_DSCR | CPU_FTR_SAO  | \
 	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
-	    CPU_FTR_DBELL | CPU_FTR_TM_COMP | CPU_FTR_BCTAR)
+	    CPU_FTR_DBELL | CPU_FTR_TM_COMP | CPU_FTR_BCTAR | CPU_FTR_DAWR)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
Signature · 1 line
1.7.10.4
#5 lore raw

PATCH 5/7 powerpc: Add DAWR/X SPR number definitions

In reply to Michael Neuling
---
 arch/powerpc/include/asm/reg.h |    5 +++++
 1 file changed, 5 insertions(+)
arch/powerpc/include/asm/reg.h +5 -0
index ce7b50e..6cae32d 100644
@@ -222,6 +222,11 @@
 #define   CTRL_CT1	0x40000000	/* thread 1 */
 #define   CTRL_TE	0x00c00000	/* thread enable */
 #define   CTRL_RUNLATCH	0x1
+#define SPRN_DAWR	0xB4
+#define SPRN_DAWRX	0xBC
+#define   DAWRX_USER	(1UL << 0)
+#define   DAWRX_KERNEL	(1UL << 1)
+#define   DAWRX_HYP	(1UL << 2)
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
 #define   DABR_TRANSLATION	(1UL << 2)
 #define   DABR_DATA_WRITE	(1UL << 1)
Signature · 1 line
1.7.10.4
#6 lore raw

PATCH 6/7 powerpc: Hardware breakpoints rewrite to handle non DABR breakpoint registers

In reply to Michael Neuling

This is a rewrite so that we don't assume we are using the DABR throughout the code. We now use the arch_hw_breakpoint to store the breakpoint in a generic manner in the thread_struct, rather than storing the raw DABR value.

The ptrace GET/SET_DEBUGREG interface currently passes the raw DABR in from userspace. We keep this functionality, so that future changes (like the POWER8 DAWR), will still fake the DABR to userspace.

---
 arch/powerpc/include/asm/debug.h         |   15 ++++---
 arch/powerpc/include/asm/hw_breakpoint.h |   33 +++++++++++---
 arch/powerpc/include/asm/processor.h     |    4 +-
 arch/powerpc/include/asm/reg.h           |    3 --
 arch/powerpc/kernel/exceptions-64s.S     |    2 +-
 arch/powerpc/kernel/hw_breakpoint.c      |   72 +++++++++++++-----------------
 arch/powerpc/kernel/kgdb.c               |   10 ++---
 arch/powerpc/kernel/process.c            |   67 ++++++++++++++++++---------
 arch/powerpc/kernel/ptrace.c             |   60 +++++++++++++------------
 arch/powerpc/kernel/ptrace32.c           |    8 +++-
 arch/powerpc/kernel/signal.c             |    5 ++-
 arch/powerpc/kernel/traps.c              |    4 +-
 arch/powerpc/mm/fault.c                  |    4 +-
 arch/powerpc/xmon/xmon.c                 |   21 ++++++---
 14 files changed, 180 insertions(+), 128 deletions(-)
arch/powerpc/include/asm/debug.h +9 -6
index 32de257..8d85ffb 100644
@@ -4,6 +4,8 @@
 #ifndef _ASM_POWERPC_DEBUG_H
 #define _ASM_POWERPC_DEBUG_H
 
+#include <asm/hw_breakpoint.h>
+
 struct pt_regs;
 
 extern struct dentry *powerpc_debugfs_root;
@@ -15,7 +17,7 @@ extern int (*__debugger_ipi)(struct pt_regs *regs);
 extern int (*__debugger_bpt)(struct pt_regs *regs);
 extern int (*__debugger_sstep)(struct pt_regs *regs);
 extern int (*__debugger_iabr_match)(struct pt_regs *regs);
-extern int (*__debugger_dabr_match)(struct pt_regs *regs);
+extern int (*__debugger_break_match)(struct pt_regs *regs);
 extern int (*__debugger_fault_handler)(struct pt_regs *regs);
 
 #define DEBUGGER_BOILERPLATE(__NAME) \
@@ -31,7 +33,7 @@ DEBUGGER_BOILERPLATE(debugger_ipi)
 DEBUGGER_BOILERPLATE(debugger_bpt)
 DEBUGGER_BOILERPLATE(debugger_sstep)
 DEBUGGER_BOILERPLATE(debugger_iabr_match)
-DEBUGGER_BOILERPLATE(debugger_dabr_match)
+DEBUGGER_BOILERPLATE(debugger_break_match)
 DEBUGGER_BOILERPLATE(debugger_fault_handler)
 
 #else
@@ -40,17 +42,18 @@ static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
 static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
 static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
 static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
-static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_break_match(struct pt_regs *regs) { return 0; }
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
-extern int set_dabr(unsigned long dabr, unsigned long dabrx);
+int set_break(struct arch_hw_breakpoint *brk);
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 extern void do_send_trap(struct pt_regs *regs, unsigned long address,
 			 unsigned long error_code, int signal_code, int brkpt);
 #else
-extern void do_dabr(struct pt_regs *regs, unsigned long address,
-		    unsigned long error_code);
+
+extern void do_break(struct pt_regs *regs, unsigned long address,
+		     unsigned long error_code);
 #endif
 
 #endif /* _ASM_POWERPC_DEBUG_H */
arch/powerpc/include/asm/hw_breakpoint.h +26 -7
index 4234245..2c91faf 100644
@@ -24,16 +24,30 @@
 #define _PPC_BOOK3S_64_HW_BREAKPOINT_H
 
 #ifdef	__KERNEL__
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
-
 struct arch_hw_breakpoint {
 	unsigned long	address;
-	unsigned long	dabrx;
-	int		type;
-	u8		len; /* length of the target data symbol */
-	bool		extraneous_interrupt;
+	u16		type;
+	u16		len; /* length of the target data symbol */
 };
 
+/* Note: Don't change the the first 6 bits below as they are in the same order
+ * as the dabr and dabrx.
+ */
+#define HW_BRK_TYPE_READ		0x01
+#define HW_BRK_TYPE_WRITE		0x02
+#define HW_BRK_TYPE_TRANSLATE		0x04
+#define HW_BRK_TYPE_USER		0x08
+#define HW_BRK_TYPE_KERNEL		0x10
+#define HW_BRK_TYPE_HYP			0x20
+#define HW_BRK_TYPE_EXTRANEOUS_IRQ	0x80
+
+/* bits that overlap with the bottom 3 bits of the dabr */
+#define HW_BRK_TYPE_RDWR	(HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)
+#define HW_BRK_TYPE_DABR	(HW_BRK_TYPE_RDWR | HW_BRK_TYPE_TRANSLATE)
+#define HW_BRK_TYPE_PRIV_ALL	(HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL | \
+				 HW_BRK_TYPE_HYP)
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
 #include <linux/kdebug.h>
 #include <asm/reg.h>
 #include <asm/debug.h>
@@ -62,7 +76,12 @@ extern void ptrace_triggered(struct perf_event *bp,
 			struct perf_sample_data *data, struct pt_regs *regs);
 static inline void hw_breakpoint_disable(void)
 {
-	set_dabr(0, 0);
+	struct arch_hw_breakpoint brk;
+
+	brk.address = 0;
+	brk.type = 0;
+	brk.len = 0;
+	set_break(&brk);
 }
 extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
 
arch/powerpc/include/asm/processor.h +2 -2
index cbbd82d..5a142c5 100644
@@ -23,6 +23,7 @@
 #include <linux/cache.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
+#include <asm/hw_breakpoint.h>
 
 /* We do _not_ want to define new machine types at all, those must die
  * in favor of using the device-tree
@@ -216,8 +217,7 @@ struct thread_struct {
 	struct perf_event *last_hit_ubp;
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
-	unsigned long	dabr;		/* Data address breakpoint register */
-	unsigned long	dabrx;		/*      ... extension  */
+	struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
 	unsigned long	trap_nr;	/* last trap # on this thread */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
arch/powerpc/include/asm/reg.h +0 -3
index 6cae32d..e9f5c05 100644
@@ -228,9 +228,6 @@
 #define   DAWRX_KERNEL	(1UL << 1)
 #define   DAWRX_HYP	(1UL << 2)
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
-#define   DABR_TRANSLATION	(1UL << 2)
-#define   DABR_DATA_WRITE	(1UL << 1)
-#define   DABR_DATA_READ	(1UL << 0)
 #define SPRN_DABR2	0x13D	/* e300 */
 #define SPRN_DABRX	0x3F7	/* Data Address Breakpoint Register Extension */
 #define   DABRX_USER	(1UL << 0)
arch/powerpc/kernel/exceptions-64s.S +1 -1
index 220b896..8ca5006 100644
@@ -1310,7 +1310,7 @@ handle_dabr_fault:
 	ld      r4,_DAR(r1)
 	ld      r5,_DSISR(r1)
 	addi    r3,r1,STACK_FRAME_OVERHEAD
-	bl      .do_dabr
+	bl      .do_break
 12:	b       .ret_from_except_lite
 
 
arch/powerpc/kernel/hw_breakpoint.c +30 -42

134 lines not on this page · raw message

arch/powerpc/kernel/kgdb.c +5 -5
index c470a40..a05f0e4 100644
@@ -198,7 +198,7 @@ static int kgdb_iabr_match(struct pt_regs *regs)
 	return 1;
 }
 
-static int kgdb_dabr_match(struct pt_regs *regs)
+static int kgdb_break_match(struct pt_regs *regs)
 {
 	if (user_mode(regs))
 		return 0;
@@ -458,7 +458,7 @@ static void *old__debugger;
 static void *old__debugger_bpt;
 static void *old__debugger_sstep;
 static void *old__debugger_iabr_match;
-static void *old__debugger_dabr_match;
+static void *old__debugger_break_match;
 static void *old__debugger_fault_handler;
 
 int kgdb_arch_init(void)
@@ -468,7 +468,7 @@ int kgdb_arch_init(void)
 	old__debugger_bpt = __debugger_bpt;
 	old__debugger_sstep = __debugger_sstep;
 	old__debugger_iabr_match = __debugger_iabr_match;
-	old__debugger_dabr_match = __debugger_dabr_match;
+	old__debugger_break_match = __debugger_break_match;
 	old__debugger_fault_handler = __debugger_fault_handler;
 
 	__debugger_ipi = kgdb_call_nmi_hook;
@@ -476,7 +476,7 @@ int kgdb_arch_init(void)
 	__debugger_bpt = kgdb_handle_breakpoint;
 	__debugger_sstep = kgdb_singlestep;
 	__debugger_iabr_match = kgdb_iabr_match;
-	__debugger_dabr_match = kgdb_dabr_match;
+	__debugger_break_match = kgdb_break_match;
 	__debugger_fault_handler = kgdb_not_implemented;
 
 	return 0;
@@ -489,6 +489,6 @@ void kgdb_arch_exit(void)
 	__debugger_bpt = old__debugger_bpt;
 	__debugger_sstep = old__debugger_sstep;
 	__debugger_iabr_match = old__debugger_iabr_match;
-	__debugger_dabr_match = old__debugger_dabr_match;
+	__debugger_breakx_match = old__debugger_break_match;
 	__debugger_fault_handler = old__debugger_fault_handler;
 }
arch/powerpc/kernel/process.c +47 -20

121 lines not on this page · raw message

arch/powerpc/kernel/ptrace.c +32 -28

149 lines not on this page · raw message

arch/powerpc/kernel/ptrace32.c +7 -1
index 8c21658..c0244e7 100644
@@ -252,6 +252,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 	}
 
 	case PTRACE_GET_DEBUGREG: {
+#ifndef CONFIG_PPC_ADV_DEBUG_REGS
+		unsigned long dabr_fake;
+#endif
 		ret = -EINVAL;
 		/* We only support one DABR and no IABRS at the moment */
 		if (addr > 0)
@@ -259,7 +262,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		ret = put_user(child->thread.dac1, (u32 __user *)data);
 #else
-		ret = put_user(child->thread.dabr, (u32 __user *)data);
+		dabr_fake = (
+			(child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) |
+			(child->thread.hw_brk.type & HW_BRK_TYPE_DABR));
+		ret = put_user(dabr_fake, (u32 __user *)data);
 #endif
 		break;
 	}
arch/powerpc/kernel/signal.c +3 -2
index 3b99711..1f26956 100644
@@ -130,8 +130,9 @@ static int do_signal(struct pt_regs *regs)
 	 * user space. The DABR will have been cleared if it
 	 * triggered inside the kernel.
 	 */
-	if (current->thread.dabr)
-		set_dabr(current->thread.dabr, current->thread.dabrx);
+	if (current->thread.hw_brk.address &&
+		current->thread.hw_brk.type)
+		set_break(&current->thread.hw_brk);
 #endif
 	/* Re-enable the breakpoints for the signal stack */
 	thread_change_pc(current, regs);
arch/powerpc/kernel/traps.c +2 -2
index cb04fc7..6a67a0d 100644
@@ -67,7 +67,7 @@ int (*__debugger_ipi)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_sstep)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_iabr_match)(struct pt_regs *regs) __read_mostly;
-int (*__debugger_dabr_match)(struct pt_regs *regs) __read_mostly;
+int (*__debugger_break_match)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_fault_handler)(struct pt_regs *regs) __read_mostly;
 
 EXPORT_SYMBOL(__debugger);
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(__debugger_ipi);
 EXPORT_SYMBOL(__debugger_bpt);
 EXPORT_SYMBOL(__debugger_sstep);
 EXPORT_SYMBOL(__debugger_iabr_match);
-EXPORT_SYMBOL(__debugger_dabr_match);
+EXPORT_SYMBOL(__debugger_break_match);
 EXPORT_SYMBOL(__debugger_fault_handler);
 #endif
 
arch/powerpc/mm/fault.c +2 -2
index 3a8489a..229951f 100644
@@ -249,8 +249,8 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE) || \
 			     defined(CONFIG_PPC_BOOK3S_64))
   	if (error_code & DSISR_DABRMATCH) {
-		/* DABR match */
-		do_dabr(regs, address, error_code);
+		/* breakpoint match */
+		do_break(regs, address, error_code);
 		return 0;
 	}
 #endif
arch/powerpc/xmon/xmon.c +14 -7
index 1f8d2f1..529c1ed 100644
@@ -43,6 +43,7 @@
 #include <asm/setjmp.h>
 #include <asm/reg.h>
 #include <asm/debug.h>
+#include <asm/hw_breakpoint.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
@@ -607,7 +608,7 @@ static int xmon_sstep(struct pt_regs *regs)
 	return 1;
 }
 
-static int xmon_dabr_match(struct pt_regs *regs)
+static int xmon_break_match(struct pt_regs *regs)
 {
 	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
 		return 0;
@@ -740,8 +741,14 @@ static void insert_bpts(void)
 
 static void insert_cpu_bpts(void)
 {
-	if (dabr.enabled)
-		set_dabr(dabr.address | (dabr.enabled & 7), DABRX_ALL);
+	struct arch_hw_breakpoint brk;
+
+	if (dabr.enabled) {
+		brk.address = dabr.address;
+		brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
+		brk.len = 8;
+		set_break(&brk);
+	}
 	if (iabr && cpu_has_feature(CPU_FTR_IABR))
 		mtspr(SPRN_IABR, iabr->address
 			 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -769,7 +776,7 @@ static void remove_bpts(void)
 
 static void remove_cpu_bpts(void)
 {
-	set_dabr(0, 0);
+	hw_breakpoint_disable();
 	if (cpu_has_feature(CPU_FTR_IABR))
 		mtspr(SPRN_IABR, 0);
 }
@@ -1138,7 +1145,7 @@ bpt_cmds(void)
 				printf(badaddr);
 				break;
 			}
-			dabr.address &= ~7;
+			dabr.address &= ~HW_BRK_TYPE_DABR;
 			dabr.enabled = mode | BP_DABR;
 		}
 		break;
@@ -2917,7 +2924,7 @@ static void xmon_init(int enable)
 		__debugger_bpt = xmon_bpt;
 		__debugger_sstep = xmon_sstep;
 		__debugger_iabr_match = xmon_iabr_match;
-		__debugger_dabr_match = xmon_dabr_match;
+		__debugger_break_match = xmon_break_match;
 		__debugger_fault_handler = xmon_fault_handler;
 	} else {
 		__debugger = NULL;
@@ -2925,7 +2932,7 @@ static void xmon_init(int enable)
 		__debugger_bpt = NULL;
 		__debugger_sstep = NULL;
 		__debugger_iabr_match = NULL;
-		__debugger_dabr_match = NULL;
+		__debugger_break_match = NULL;
 		__debugger_fault_handler = NULL;
 	}
 }
Signature · 1 line
1.7.10.4
#7 lore raw

PATCH 6/7 powerpc: Hardware breakpoints rewrite to handle non DABR breakpoint registers

This is a rewrite so that we don't assume we are using the DABR throughout the code. We now use the arch_hw_breakpoint to store the breakpoint in a generic manner in the thread_struct, rather than storing the raw DABR value.

The ptrace GET/SET_DEBUGREG interface currently passes the raw DABR in from userspace. We keep this functionality, so that future changes (like the POWER8 DAWR), will still fake the DABR to userspace.

---
Resending to fix a problem with 8xx defconfigs. Noticed by benh.

 arch/powerpc/include/asm/debug.h         |   15 +++---
 arch/powerpc/include/asm/hw_breakpoint.h |   33 ++++++++++---
 arch/powerpc/include/asm/processor.h     |    4 +-
 arch/powerpc/include/asm/reg.h           |    3 --
 arch/powerpc/kernel/exceptions-64s.S     |    2 +-
 arch/powerpc/kernel/hw_breakpoint.c      |   72 ++++++++++++----------------
 arch/powerpc/kernel/kgdb.c               |   10 ++--
 arch/powerpc/kernel/process.c            |   75 +++++++++++++++++++++---------
 arch/powerpc/kernel/ptrace.c             |   60 +++++++++++++-----------
 arch/powerpc/kernel/ptrace32.c           |    8 +++-
 arch/powerpc/kernel/signal.c             |    5 +-
 arch/powerpc/kernel/traps.c              |    4 +-
 arch/powerpc/mm/fault.c                  |    4 +-
 arch/powerpc/xmon/xmon.c                 |   21 ++++++---
 14 files changed, 187 insertions(+), 129 deletions(-)
arch/powerpc/include/asm/debug.h +9 -6
index 32de257..8d85ffb 100644
@@ -4,6 +4,8 @@
 #ifndef _ASM_POWERPC_DEBUG_H
 #define _ASM_POWERPC_DEBUG_H
 
+#include <asm/hw_breakpoint.h>
+
 struct pt_regs;
 
 extern struct dentry *powerpc_debugfs_root;
@@ -15,7 +17,7 @@ extern int (*__debugger_ipi)(struct pt_regs *regs);
 extern int (*__debugger_bpt)(struct pt_regs *regs);
 extern int (*__debugger_sstep)(struct pt_regs *regs);
 extern int (*__debugger_iabr_match)(struct pt_regs *regs);
-extern int (*__debugger_dabr_match)(struct pt_regs *regs);
+extern int (*__debugger_break_match)(struct pt_regs *regs);
 extern int (*__debugger_fault_handler)(struct pt_regs *regs);
 
 #define DEBUGGER_BOILERPLATE(__NAME) \
@@ -31,7 +33,7 @@ DEBUGGER_BOILERPLATE(debugger_ipi)
 DEBUGGER_BOILERPLATE(debugger_bpt)
 DEBUGGER_BOILERPLATE(debugger_sstep)
 DEBUGGER_BOILERPLATE(debugger_iabr_match)
-DEBUGGER_BOILERPLATE(debugger_dabr_match)
+DEBUGGER_BOILERPLATE(debugger_break_match)
 DEBUGGER_BOILERPLATE(debugger_fault_handler)
 
 #else
@@ -40,17 +42,18 @@ static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
 static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
 static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
 static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
-static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_break_match(struct pt_regs *regs) { return 0; }
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
-extern int set_dabr(unsigned long dabr, unsigned long dabrx);
+int set_break(struct arch_hw_breakpoint *brk);
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 extern void do_send_trap(struct pt_regs *regs, unsigned long address,
 			 unsigned long error_code, int signal_code, int brkpt);
 #else
-extern void do_dabr(struct pt_regs *regs, unsigned long address,
-		    unsigned long error_code);
+
+extern void do_break(struct pt_regs *regs, unsigned long address,
+		     unsigned long error_code);
 #endif
 
 #endif /* _ASM_POWERPC_DEBUG_H */
arch/powerpc/include/asm/hw_breakpoint.h +26 -7
index 4234245..2c91faf 100644
@@ -24,16 +24,30 @@
 #define _PPC_BOOK3S_64_HW_BREAKPOINT_H
 
 #ifdef	__KERNEL__
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
-
 struct arch_hw_breakpoint {
 	unsigned long	address;
-	unsigned long	dabrx;
-	int		type;
-	u8		len; /* length of the target data symbol */
-	bool		extraneous_interrupt;
+	u16		type;
+	u16		len; /* length of the target data symbol */
 };
 
+/* Note: Don't change the the first 6 bits below as they are in the same order
+ * as the dabr and dabrx.
+ */
+#define HW_BRK_TYPE_READ		0x01
+#define HW_BRK_TYPE_WRITE		0x02
+#define HW_BRK_TYPE_TRANSLATE		0x04
+#define HW_BRK_TYPE_USER		0x08
+#define HW_BRK_TYPE_KERNEL		0x10
+#define HW_BRK_TYPE_HYP			0x20
+#define HW_BRK_TYPE_EXTRANEOUS_IRQ	0x80
+
+/* bits that overlap with the bottom 3 bits of the dabr */
+#define HW_BRK_TYPE_RDWR	(HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)
+#define HW_BRK_TYPE_DABR	(HW_BRK_TYPE_RDWR | HW_BRK_TYPE_TRANSLATE)
+#define HW_BRK_TYPE_PRIV_ALL	(HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL | \
+				 HW_BRK_TYPE_HYP)
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
 #include <linux/kdebug.h>
 #include <asm/reg.h>
 #include <asm/debug.h>
@@ -62,7 +76,12 @@ extern void ptrace_triggered(struct perf_event *bp,
 			struct perf_sample_data *data, struct pt_regs *regs);
 static inline void hw_breakpoint_disable(void)
 {
-	set_dabr(0, 0);
+	struct arch_hw_breakpoint brk;
+
+	brk.address = 0;
+	brk.type = 0;
+	brk.len = 0;
+	set_break(&brk);
 }
 extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
 
arch/powerpc/include/asm/processor.h +2 -2
index cbbd82d..5a142c5 100644
@@ -23,6 +23,7 @@
 #include <linux/cache.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
+#include <asm/hw_breakpoint.h>
 
 /* We do _not_ want to define new machine types at all, those must die
  * in favor of using the device-tree
@@ -216,8 +217,7 @@ struct thread_struct {
 	struct perf_event *last_hit_ubp;
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
-	unsigned long	dabr;		/* Data address breakpoint register */
-	unsigned long	dabrx;		/*      ... extension  */
+	struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
 	unsigned long	trap_nr;	/* last trap # on this thread */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
arch/powerpc/include/asm/reg.h +0 -3
index 76e4bd0..be16699 100644
@@ -227,9 +227,6 @@
 #define   DAWRX_KERNEL	(1UL << 1)
 #define   DAWRX_HYP	(1UL << 2)
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
-#define   DABR_TRANSLATION	(1UL << 2)
-#define   DABR_DATA_WRITE	(1UL << 1)
-#define   DABR_DATA_READ	(1UL << 0)
 #define SPRN_DABR2	0x13D	/* e300 */
 #define SPRN_DABRX	0x3F7	/* Data Address Breakpoint Register Extension */
 #define   DABRX_USER	(1UL << 0)
arch/powerpc/kernel/exceptions-64s.S +1 -1
index 220b896..8ca5006 100644
@@ -1310,7 +1310,7 @@ handle_dabr_fault:
 	ld      r4,_DAR(r1)
 	ld      r5,_DSISR(r1)
 	addi    r3,r1,STACK_FRAME_OVERHEAD
-	bl      .do_dabr
+	bl      .do_break
 12:	b       .ret_from_except_lite
 
 
arch/powerpc/kernel/hw_breakpoint.c +30 -42

134 lines not on this page · raw message

arch/powerpc/kernel/kgdb.c +5 -5
index c470a40..a05f0e4 100644
@@ -198,7 +198,7 @@ static int kgdb_iabr_match(struct pt_regs *regs)
 	return 1;
 }
 
-static int kgdb_dabr_match(struct pt_regs *regs)
+static int kgdb_break_match(struct pt_regs *regs)
 {
 	if (user_mode(regs))
 		return 0;
@@ -458,7 +458,7 @@ static void *old__debugger;
 static void *old__debugger_bpt;
 static void *old__debugger_sstep;
 static void *old__debugger_iabr_match;
-static void *old__debugger_dabr_match;
+static void *old__debugger_break_match;
 static void *old__debugger_fault_handler;
 
 int kgdb_arch_init(void)
@@ -468,7 +468,7 @@ int kgdb_arch_init(void)
 	old__debugger_bpt = __debugger_bpt;
 	old__debugger_sstep = __debugger_sstep;
 	old__debugger_iabr_match = __debugger_iabr_match;
-	old__debugger_dabr_match = __debugger_dabr_match;
+	old__debugger_break_match = __debugger_break_match;
 	old__debugger_fault_handler = __debugger_fault_handler;
 
 	__debugger_ipi = kgdb_call_nmi_hook;
@@ -476,7 +476,7 @@ int kgdb_arch_init(void)
 	__debugger_bpt = kgdb_handle_breakpoint;
 	__debugger_sstep = kgdb_singlestep;
 	__debugger_iabr_match = kgdb_iabr_match;
-	__debugger_dabr_match = kgdb_dabr_match;
+	__debugger_break_match = kgdb_break_match;
 	__debugger_fault_handler = kgdb_not_implemented;
 
 	return 0;
@@ -489,6 +489,6 @@ void kgdb_arch_exit(void)
 	__debugger_bpt = old__debugger_bpt;
 	__debugger_sstep = old__debugger_sstep;
 	__debugger_iabr_match = old__debugger_iabr_match;
-	__debugger_dabr_match = old__debugger_dabr_match;
+	__debugger_breakx_match = old__debugger_break_match;
 	__debugger_fault_handler = old__debugger_fault_handler;
 }
arch/powerpc/kernel/process.c +54 -21

127 lines not on this page · raw message

arch/powerpc/kernel/ptrace.c +32 -28

149 lines not on this page · raw message

arch/powerpc/kernel/ptrace32.c +7 -1
index 8c21658..c0244e7 100644
@@ -252,6 +252,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 	}
 
 	case PTRACE_GET_DEBUGREG: {
+#ifndef CONFIG_PPC_ADV_DEBUG_REGS
+		unsigned long dabr_fake;
+#endif
 		ret = -EINVAL;
 		/* We only support one DABR and no IABRS at the moment */
 		if (addr > 0)
@@ -259,7 +262,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		ret = put_user(child->thread.dac1, (u32 __user *)data);
 #else
-		ret = put_user(child->thread.dabr, (u32 __user *)data);
+		dabr_fake = (
+			(child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) |
+			(child->thread.hw_brk.type & HW_BRK_TYPE_DABR));
+		ret = put_user(dabr_fake, (u32 __user *)data);
 #endif
 		break;
 	}
arch/powerpc/kernel/signal.c +3 -2
index 3b99711..1f26956 100644
@@ -130,8 +130,9 @@ static int do_signal(struct pt_regs *regs)
 	 * user space. The DABR will have been cleared if it
 	 * triggered inside the kernel.
 	 */
-	if (current->thread.dabr)
-		set_dabr(current->thread.dabr, current->thread.dabrx);
+	if (current->thread.hw_brk.address &&
+		current->thread.hw_brk.type)
+		set_break(&current->thread.hw_brk);
 #endif
 	/* Re-enable the breakpoints for the signal stack */
 	thread_change_pc(current, regs);
arch/powerpc/kernel/traps.c +2 -2
index cb04fc7..6a67a0d 100644
@@ -67,7 +67,7 @@ int (*__debugger_ipi)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_sstep)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_iabr_match)(struct pt_regs *regs) __read_mostly;
-int (*__debugger_dabr_match)(struct pt_regs *regs) __read_mostly;
+int (*__debugger_break_match)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_fault_handler)(struct pt_regs *regs) __read_mostly;
 
 EXPORT_SYMBOL(__debugger);
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(__debugger_ipi);
 EXPORT_SYMBOL(__debugger_bpt);
 EXPORT_SYMBOL(__debugger_sstep);
 EXPORT_SYMBOL(__debugger_iabr_match);
-EXPORT_SYMBOL(__debugger_dabr_match);
+EXPORT_SYMBOL(__debugger_break_match);
 EXPORT_SYMBOL(__debugger_fault_handler);
 #endif
 
arch/powerpc/mm/fault.c +2 -2
index 3a8489a..229951f 100644
@@ -249,8 +249,8 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE) || \
 			     defined(CONFIG_PPC_BOOK3S_64))
   	if (error_code & DSISR_DABRMATCH) {
-		/* DABR match */
-		do_dabr(regs, address, error_code);
+		/* breakpoint match */
+		do_break(regs, address, error_code);
 		return 0;
 	}
 #endif
arch/powerpc/xmon/xmon.c +14 -7
index 1f8d2f1..529c1ed 100644
@@ -43,6 +43,7 @@
 #include <asm/setjmp.h>
 #include <asm/reg.h>
 #include <asm/debug.h>
+#include <asm/hw_breakpoint.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
@@ -607,7 +608,7 @@ static int xmon_sstep(struct pt_regs *regs)
 	return 1;
 }
 
-static int xmon_dabr_match(struct pt_regs *regs)
+static int xmon_break_match(struct pt_regs *regs)
 {
 	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
 		return 0;
@@ -740,8 +741,14 @@ static void insert_bpts(void)
 
 static void insert_cpu_bpts(void)
 {
-	if (dabr.enabled)
-		set_dabr(dabr.address | (dabr.enabled & 7), DABRX_ALL);
+	struct arch_hw_breakpoint brk;
+
+	if (dabr.enabled) {
+		brk.address = dabr.address;
+		brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
+		brk.len = 8;
+		set_break(&brk);
+	}
 	if (iabr && cpu_has_feature(CPU_FTR_IABR))
 		mtspr(SPRN_IABR, iabr->address
 			 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -769,7 +776,7 @@ static void remove_bpts(void)
 
 static void remove_cpu_bpts(void)
 {
-	set_dabr(0, 0);
+	hw_breakpoint_disable();
 	if (cpu_has_feature(CPU_FTR_IABR))
 		mtspr(SPRN_IABR, 0);
 }
@@ -1138,7 +1145,7 @@ bpt_cmds(void)
 				printf(badaddr);
 				break;
 			}
-			dabr.address &= ~7;
+			dabr.address &= ~HW_BRK_TYPE_DABR;
 			dabr.enabled = mode | BP_DABR;
 		}
 		break;
@@ -2917,7 +2924,7 @@ static void xmon_init(int enable)
 		__debugger_bpt = xmon_bpt;
 		__debugger_sstep = xmon_sstep;
 		__debugger_iabr_match = xmon_iabr_match;
-		__debugger_dabr_match = xmon_dabr_match;
+		__debugger_break_match = xmon_break_match;
 		__debugger_fault_handler = xmon_fault_handler;
 	} else {
 		__debugger = NULL;
@@ -2925,7 +2932,7 @@ static void xmon_init(int enable)
 		__debugger_bpt = NULL;
 		__debugger_sstep = NULL;
 		__debugger_iabr_match = NULL;
-		__debugger_dabr_match = NULL;
+		__debugger_break_match = NULL;
 		__debugger_fault_handler = NULL;
 	}
 }
Signature · 1 line
1.7.10.4
#8 lore raw

PATCH 1/1 powerpc: Fix typo in breakpoint kgdb code.

In reply to Michael Neuling

Currently we are getting:
arch/powerpc/kernel/kgdb.c: In function 'kgdb_arch_exit':
arch/powerpc/kernel/kgdb.c:492:2: error: '__debugger_breakx_match' undeclared (first use in this function) arch/powerpc/kernel/kgdb.c:492:2: note: each undeclared identifier is reported only once for each function it appears in

Fix the typo.

---
Stupid error. I guess my defconfigs didn't compile this code... sorry.

arch/powerpc/kernel/kgdb.c +1 -1
index a05f0e4..8747447 100644
@@ -489,6 +489,6 @@ void kgdb_arch_exit(void)
 	__debugger_bpt = old__debugger_bpt;
 	__debugger_sstep = old__debugger_sstep;
 	__debugger_iabr_match = old__debugger_iabr_match;
-	__debugger_breakx_match = old__debugger_break_match;
+	__debugger_break_match = old__debugger_break_match;
 	__debugger_fault_handler = old__debugger_fault_handler;
 }

A message that is not in the archive (sent off-list or not yet received): 12813.1357794092__45363.9676016339$1357794149$gmane$org@ale.ozlabs.ibm.com

#10 lore raw

PATCH 1/1 powerpc: fix hw breakpoints on !HAVE_HW_BREAKPOINT configurations

This fixes a logic error that caused a failure to update the hw breakpoint registers when not using the hw-breakpoint interface.

---
 arch/powerpc/kernel/process.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/process.c +1 -1
index 4a96556..7714950 100644
@@ -690,7 +690,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
  * schedule DABR
  */
 #ifndef CONFIG_HAVE_HW_BREAKPOINT
-	if (unlikely(hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk)))
+	if (unlikely(!hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk)))
 		set_breakpoint(&new->thread.hw_brk);
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
Signature · 7 lines
1.8.5.3


-- 
Andreas Schwab, [email protected]
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
#11 lore raw

Re: [PATCH] powerpc: fix hw breakpoints on !HAVE_HW_BREAKPOINT configurations

I'm not near my machine to test but looks good.

Thanks,
Mikey

Quoted 34 lines · Andreas Schwab

This fixes a logic error that caused a failure to update the hw breakpoint registers when not using the hw-breakpoint interface.

---
 arch/powerpc/kernel/process.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/process.c +1 -1
index 4a96556..7714950 100644
@@ -690,7 +690,7 @@ struct task_struct *__switch_to(struct task_struct
 *prev,
  * schedule DABR
  */
 #ifndef CONFIG_HAVE_HW_BREAKPOINT
-       if (unlikely(hw_brk_match(&__get_cpu_var(current_brk),
 &new->thread.hw_brk)))
+       if (unlikely(!hw_brk_match(&__get_cpu_var(current_brk),
 &new->thread.hw_brk)))
                set_breakpoint(&new->thread.hw_brk);

#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif
--
1.8.5.3

--
Andreas Schwab, [email protected]
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."

#12 lore raw

PATCH 7/7 powerpc: Add the DAWR support to the set_break()

In reply to Michael Neuling

This adds DAWR supoprt to the set_break().

It does both bare metal and PAPR versions of setting the DAWR.

There is still some work we can do to make full use of the watchpoint but that will come later.

---
 arch/powerpc/include/asm/machdep.h     |    4 ++++
 arch/powerpc/kernel/process.c          |   23 +++++++++++++++++++++++
 arch/powerpc/platforms/pseries/setup.c |   12 ++++++++++++
 3 files changed, 39 insertions(+)
arch/powerpc/include/asm/machdep.h +4 -0
index 19d9d96..3d6b410 100644
@@ -180,6 +180,10 @@ struct machdep_calls {
 	int		(*set_dabr)(unsigned long dabr,
 				    unsigned long dabrx);
 
+	/* Set DAWR for this platform, leave empty for default implemenation */
+	int		(*set_dawr)(unsigned long dawr,
+				    unsigned long dawrx);
+
 #ifdef CONFIG_PPC32	/* XXX for now */
 	/* A general init function, called by ppc_init in init/main.c.
 	   May be NULL. */
arch/powerpc/kernel/process.c +23 -0
index 5a64028..fec5f46 100644
@@ -412,10 +412,33 @@ static inline int set_dabr(struct arch_hw_breakpoint *brk)
 	return 0;
 }
 
+static inline int set_dawr(struct arch_hw_breakpoint *brk)
+{
+	unsigned long dawr, dawrx;
+
+	dawr = brk->address;
+
+	dawrx  = (brk->type & (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)) \
+		                   << (63 - 58); //* read/write bits */
+	dawrx |= ((brk->type & (HW_BRK_TYPE_TRANSLATE)) >> 2) \
+		                   << (63 - 59); //* translate */
+	dawrx |= (brk->type & (HW_BRK_TYPE_PRIV_ALL)) \
+		                   >> 3; //* PRIM bits */
+
+	if (ppc_md.set_dawr)
+		return ppc_md.set_dawr(dawr, dawrx);
+	mtspr(SPRN_DAWR, dawr);
+	mtspr(SPRN_DAWRX, dawrx);
+	return 0;
+}
+
 int set_break(struct arch_hw_breakpoint *brk)
 {
 	__get_cpu_var(current_brk) = *brk;
 
+	if (cpu_has_feature(CPU_FTR_DAWR))
+		return set_dawr(brk);
+
 	return set_dabr(brk);
 }
 
arch/powerpc/platforms/pseries/setup.c +12 -0
index 1890730..b1f60d1 100644
@@ -65,6 +65,7 @@
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/eeh.h>
+#include <asm/reg.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
@@ -500,6 +501,14 @@ static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx)
 	return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx);
 }
 
+static int pseries_set_dawr(unsigned long dawr, unsigned long dawrx)
+{
+	/* PAPR says we can't set HYP */
+	dawrx &= ~DAWRX_HYP;
+
+	return  plapr_set_watchpoint0(dawr, dawrx);
+}
+
 #define CMO_CHARACTERISTICS_TOKEN 44
 #define CMO_MAXLENGTH 1026
 
@@ -606,6 +615,9 @@ static void __init pSeries_init_early(void)
 	else if (firmware_has_feature(FW_FEATURE_DABR))
 		ppc_md.set_dabr = pseries_set_dabr;
 
+	if (firmware_has_feature(FW_FEATURE_SET_MODE))
+		ppc_md.set_dawr = pseries_set_dawr;
+
 	pSeries_cmo_feature_init();
 	iommu_init_early_pSeries();
 
Signature · 1 line
1.7.10.4