aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2012-12-20 09:06:44 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-01-10 01:01:44 -0500
commit9422de3e953d0e60eb95f5430a9dd803eec1c6d7 (patch)
tree7255a4a2b873a0c3daf7b312a0845202edf6b2d5 /arch
parenta8190a59e7440a7e3f7c0889d72a13e157988b3c (diff)
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. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/debug.h15
-rw-r--r--arch/powerpc/include/asm/hw_breakpoint.h33
-rw-r--r--arch/powerpc/include/asm/processor.h4
-rw-r--r--arch/powerpc/include/asm/reg.h3
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S2
-rw-r--r--arch/powerpc/kernel/hw_breakpoint.c72
-rw-r--r--arch/powerpc/kernel/kgdb.c10
-rw-r--r--arch/powerpc/kernel/process.c75
-rw-r--r--arch/powerpc/kernel/ptrace.c60
-rw-r--r--arch/powerpc/kernel/ptrace32.c8
-rw-r--r--arch/powerpc/kernel/signal.c5
-rw-r--r--arch/powerpc/kernel/traps.c4
-rw-r--r--arch/powerpc/mm/fault.c4
-rw-r--r--arch/powerpc/xmon/xmon.c21
14 files changed, 187 insertions, 129 deletions
diff --git a/arch/powerpc/include/asm/debug.h b/arch/powerpc/include/asm/debug.h
index 32de2577bb6d..8d85ffb03e61 100644
--- a/arch/powerpc/include/asm/debug.h
+++ b/arch/powerpc/include/asm/debug.h
@@ -4,6 +4,8 @@
4#ifndef _ASM_POWERPC_DEBUG_H 4#ifndef _ASM_POWERPC_DEBUG_H
5#define _ASM_POWERPC_DEBUG_H 5#define _ASM_POWERPC_DEBUG_H
6 6
7#include <asm/hw_breakpoint.h>
8
7struct pt_regs; 9struct pt_regs;
8 10
9extern struct dentry *powerpc_debugfs_root; 11extern struct dentry *powerpc_debugfs_root;
@@ -15,7 +17,7 @@ extern int (*__debugger_ipi)(struct pt_regs *regs);
15extern int (*__debugger_bpt)(struct pt_regs *regs); 17extern int (*__debugger_bpt)(struct pt_regs *regs);
16extern int (*__debugger_sstep)(struct pt_regs *regs); 18extern int (*__debugger_sstep)(struct pt_regs *regs);
17extern int (*__debugger_iabr_match)(struct pt_regs *regs); 19extern int (*__debugger_iabr_match)(struct pt_regs *regs);
18extern int (*__debugger_dabr_match)(struct pt_regs *regs); 20extern int (*__debugger_break_match)(struct pt_regs *regs);
19extern int (*__debugger_fault_handler)(struct pt_regs *regs); 21extern int (*__debugger_fault_handler)(struct pt_regs *regs);
20 22
21#define DEBUGGER_BOILERPLATE(__NAME) \ 23#define DEBUGGER_BOILERPLATE(__NAME) \
@@ -31,7 +33,7 @@ DEBUGGER_BOILERPLATE(debugger_ipi)
31DEBUGGER_BOILERPLATE(debugger_bpt) 33DEBUGGER_BOILERPLATE(debugger_bpt)
32DEBUGGER_BOILERPLATE(debugger_sstep) 34DEBUGGER_BOILERPLATE(debugger_sstep)
33DEBUGGER_BOILERPLATE(debugger_iabr_match) 35DEBUGGER_BOILERPLATE(debugger_iabr_match)
34DEBUGGER_BOILERPLATE(debugger_dabr_match) 36DEBUGGER_BOILERPLATE(debugger_break_match)
35DEBUGGER_BOILERPLATE(debugger_fault_handler) 37DEBUGGER_BOILERPLATE(debugger_fault_handler)
36 38
37#else 39#else
@@ -40,17 +42,18 @@ static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
40static inline int debugger_bpt(struct pt_regs *regs) { return 0; } 42static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
41static inline int debugger_sstep(struct pt_regs *regs) { return 0; } 43static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
42static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; } 44static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
43static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; } 45static inline int debugger_break_match(struct pt_regs *regs) { return 0; }
44static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } 46static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
45#endif 47#endif
46 48
47extern int set_dabr(unsigned long dabr, unsigned long dabrx); 49int set_break(struct arch_hw_breakpoint *brk);
48#ifdef CONFIG_PPC_ADV_DEBUG_REGS 50#ifdef CONFIG_PPC_ADV_DEBUG_REGS
49extern void do_send_trap(struct pt_regs *regs, unsigned long address, 51extern void do_send_trap(struct pt_regs *regs, unsigned long address,
50 unsigned long error_code, int signal_code, int brkpt); 52 unsigned long error_code, int signal_code, int brkpt);
51#else 53#else
52extern void do_dabr(struct pt_regs *regs, unsigned long address, 54
53 unsigned long error_code); 55extern void do_break(struct pt_regs *regs, unsigned long address,
56 unsigned long error_code);
54#endif 57#endif
55 58
56#endif /* _ASM_POWERPC_DEBUG_H */ 59#endif /* _ASM_POWERPC_DEBUG_H */
diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h
index 423424599dad..2c91faf981db 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -24,16 +24,30 @@
24#define _PPC_BOOK3S_64_HW_BREAKPOINT_H 24#define _PPC_BOOK3S_64_HW_BREAKPOINT_H
25 25
26#ifdef __KERNEL__ 26#ifdef __KERNEL__
27#ifdef CONFIG_HAVE_HW_BREAKPOINT
28
29struct arch_hw_breakpoint { 27struct arch_hw_breakpoint {
30 unsigned long address; 28 unsigned long address;
31 unsigned long dabrx; 29 u16 type;
32 int type; 30 u16 len; /* length of the target data symbol */
33 u8 len; /* length of the target data symbol */
34 bool extraneous_interrupt;
35}; 31};
36 32
33/* Note: Don't change the the first 6 bits below as they are in the same order
34 * as the dabr and dabrx.
35 */
36#define HW_BRK_TYPE_READ 0x01
37#define HW_BRK_TYPE_WRITE 0x02
38#define HW_BRK_TYPE_TRANSLATE 0x04
39#define HW_BRK_TYPE_USER 0x08
40#define HW_BRK_TYPE_KERNEL 0x10
41#define HW_BRK_TYPE_HYP 0x20
42#define HW_BRK_TYPE_EXTRANEOUS_IRQ 0x80
43
44/* bits that overlap with the bottom 3 bits of the dabr */
45#define HW_BRK_TYPE_RDWR (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)
46#define HW_BRK_TYPE_DABR (HW_BRK_TYPE_RDWR | HW_BRK_TYPE_TRANSLATE)
47#define HW_BRK_TYPE_PRIV_ALL (HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL | \
48 HW_BRK_TYPE_HYP)
49
50#ifdef CONFIG_HAVE_HW_BREAKPOINT
37#include <linux/kdebug.h> 51#include <linux/kdebug.h>
38#include <asm/reg.h> 52#include <asm/reg.h>
39#include <asm/debug.h> 53#include <asm/debug.h>
@@ -62,7 +76,12 @@ extern void ptrace_triggered(struct perf_event *bp,
62 struct perf_sample_data *data, struct pt_regs *regs); 76 struct perf_sample_data *data, struct pt_regs *regs);
63static inline void hw_breakpoint_disable(void) 77static inline void hw_breakpoint_disable(void)
64{ 78{
65 set_dabr(0, 0); 79 struct arch_hw_breakpoint brk;
80
81 brk.address = 0;
82 brk.type = 0;
83 brk.len = 0;
84 set_break(&brk);
66} 85}
67extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs); 86extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
68 87
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 37f87f069cbf..7938658c168d 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -33,6 +33,7 @@
33#include <linux/cache.h> 33#include <linux/cache.h>
34#include <asm/ptrace.h> 34#include <asm/ptrace.h>
35#include <asm/types.h> 35#include <asm/types.h>
36#include <asm/hw_breakpoint.h>
36 37
37/* We do _not_ want to define new machine types at all, those must die 38/* We do _not_ want to define new machine types at all, those must die
38 * in favor of using the device-tree 39 * in favor of using the device-tree
@@ -225,8 +226,7 @@ struct thread_struct {
225 struct perf_event *last_hit_ubp; 226 struct perf_event *last_hit_ubp;
226#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 227#endif /* CONFIG_HAVE_HW_BREAKPOINT */
227#endif 228#endif
228 unsigned long dabr; /* Data address breakpoint register */ 229 struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
229 unsigned long dabrx; /* ... extension */
230 unsigned long trap_nr; /* last trap # on this thread */ 230 unsigned long trap_nr; /* last trap # on this thread */
231#ifdef CONFIG_ALTIVEC 231#ifdef CONFIG_ALTIVEC
232 /* Complete AltiVec register set */ 232 /* Complete AltiVec register set */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index d111beb1acdb..1f59fbb7b054 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -206,9 +206,6 @@
206#define DAWRX_KERNEL (1UL << 1) 206#define DAWRX_KERNEL (1UL << 1)
207#define DAWRX_HYP (1UL << 2) 207#define DAWRX_HYP (1UL << 2)
208#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ 208#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
209#define DABR_TRANSLATION (1UL << 2)
210#define DABR_DATA_WRITE (1UL << 1)
211#define DABR_DATA_READ (1UL << 0)
212#define SPRN_DABR2 0x13D /* e300 */ 209#define SPRN_DABR2 0x13D /* e300 */
213#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */ 210#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */
214#define DABRX_USER (1UL << 0) 211#define DABRX_USER (1UL << 0)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 3425aba8da51..a28a65fd0f07 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1251,7 +1251,7 @@ handle_dabr_fault:
1251 ld r4,_DAR(r1) 1251 ld r4,_DAR(r1)
1252 ld r5,_DSISR(r1) 1252 ld r5,_DSISR(r1)
1253 addi r3,r1,STACK_FRAME_OVERHEAD 1253 addi r3,r1,STACK_FRAME_OVERHEAD
1254 bl .do_dabr 1254 bl .do_break
125512: b .ret_from_except_lite 125512: b .ret_from_except_lite
1256 1256
1257 1257
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index a89cae481b04..c7483d09fdd0 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -73,7 +73,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
73 * If so, DABR will be populated in single_step_dabr_instruction(). 73 * If so, DABR will be populated in single_step_dabr_instruction().
74 */ 74 */
75 if (current->thread.last_hit_ubp != bp) 75 if (current->thread.last_hit_ubp != bp)
76 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx); 76 set_break(info);
77 77
78 return 0; 78 return 0;
79} 79}
@@ -97,7 +97,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
97 } 97 }
98 98
99 *slot = NULL; 99 *slot = NULL;
100 set_dabr(0, 0); 100 hw_breakpoint_disable();
101} 101}
102 102
103/* 103/*
@@ -127,19 +127,13 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
127 127
128int arch_bp_generic_fields(int type, int *gen_bp_type) 128int arch_bp_generic_fields(int type, int *gen_bp_type)
129{ 129{
130 switch (type) { 130 *gen_bp_type = 0;
131 case DABR_DATA_READ: 131 if (type & HW_BRK_TYPE_READ)
132 *gen_bp_type = HW_BREAKPOINT_R; 132 *gen_bp_type |= HW_BREAKPOINT_R;
133 break; 133 if (type & HW_BRK_TYPE_WRITE)
134 case DABR_DATA_WRITE: 134 *gen_bp_type |= HW_BREAKPOINT_W;
135 *gen_bp_type = HW_BREAKPOINT_W; 135 if (*gen_bp_type == 0)
136 break;
137 case (DABR_DATA_WRITE | DABR_DATA_READ):
138 *gen_bp_type = (HW_BREAKPOINT_W | HW_BREAKPOINT_R);
139 break;
140 default:
141 return -EINVAL; 136 return -EINVAL;
142 }
143 return 0; 137 return 0;
144} 138}
145 139
@@ -154,29 +148,22 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
154 if (!bp) 148 if (!bp)
155 return ret; 149 return ret;
156 150
157 switch (bp->attr.bp_type) { 151 info->type = HW_BRK_TYPE_TRANSLATE;
158 case HW_BREAKPOINT_R: 152 if (bp->attr.bp_type & HW_BREAKPOINT_R)
159 info->type = DABR_DATA_READ; 153 info->type |= HW_BRK_TYPE_READ;
160 break; 154 if (bp->attr.bp_type & HW_BREAKPOINT_W)
161 case HW_BREAKPOINT_W: 155 info->type |= HW_BRK_TYPE_WRITE;
162 info->type = DABR_DATA_WRITE; 156 if (info->type == HW_BRK_TYPE_TRANSLATE)
163 break; 157 /* must set alteast read or write */
164 case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
165 info->type = (DABR_DATA_READ | DABR_DATA_WRITE);
166 break;
167 default:
168 return ret; 158 return ret;
169 } 159 if (!(bp->attr.exclude_user))
170 160 info->type |= HW_BRK_TYPE_USER;
161 if (!(bp->attr.exclude_kernel))
162 info->type |= HW_BRK_TYPE_KERNEL;
163 if (!(bp->attr.exclude_hv))
164 info->type |= HW_BRK_TYPE_HYP;
171 info->address = bp->attr.bp_addr; 165 info->address = bp->attr.bp_addr;
172 info->len = bp->attr.bp_len; 166 info->len = bp->attr.bp_len;
173 info->dabrx = DABRX_ALL;
174 if (bp->attr.exclude_user)
175 info->dabrx &= ~DABRX_USER;
176 if (bp->attr.exclude_kernel)
177 info->dabrx &= ~DABRX_KERNEL;
178 if (bp->attr.exclude_hv)
179 info->dabrx &= ~DABRX_HYP;
180 167
181 /* 168 /*
182 * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8) 169 * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
@@ -204,7 +191,7 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
204 191
205 info = counter_arch_bp(tsk->thread.last_hit_ubp); 192 info = counter_arch_bp(tsk->thread.last_hit_ubp);
206 regs->msr &= ~MSR_SE; 193 regs->msr &= ~MSR_SE;
207 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx); 194 set_break(info);
208 tsk->thread.last_hit_ubp = NULL; 195 tsk->thread.last_hit_ubp = NULL;
209} 196}
210 197
@@ -222,7 +209,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
222 unsigned long dar = regs->dar; 209 unsigned long dar = regs->dar;
223 210
224 /* Disable breakpoints during exception handling */ 211 /* Disable breakpoints during exception handling */
225 set_dabr(0, 0); 212 hw_breakpoint_disable();
226 213
227 /* 214 /*
228 * The counter may be concurrently released but that can only 215 * The counter may be concurrently released but that can only
@@ -255,8 +242,9 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
255 * we still need to single-step the instruction, but we don't 242 * we still need to single-step the instruction, but we don't
256 * generate an event. 243 * generate an event.
257 */ 244 */
258 info->extraneous_interrupt = !((bp->attr.bp_addr <= dar) && 245 if (!((bp->attr.bp_addr <= dar) &&
259 (dar - bp->attr.bp_addr < bp->attr.bp_len)); 246 (dar - bp->attr.bp_addr < bp->attr.bp_len)))
247 info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
260 248
261 /* Do not emulate user-space instructions, instead single-step them */ 249 /* Do not emulate user-space instructions, instead single-step them */
262 if (user_mode(regs)) { 250 if (user_mode(regs)) {
@@ -285,10 +273,10 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
285 * As a policy, the callback is invoked in a 'trigger-after-execute' 273 * As a policy, the callback is invoked in a 'trigger-after-execute'
286 * fashion 274 * fashion
287 */ 275 */
288 if (!info->extraneous_interrupt) 276 if (!(info->type & HW_BRK_TYPE_EXTRANEOUS_IRQ))
289 perf_bp_event(bp, regs); 277 perf_bp_event(bp, regs);
290 278
291 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx); 279 set_break(info);
292out: 280out:
293 rcu_read_unlock(); 281 rcu_read_unlock();
294 return rc; 282 return rc;
@@ -317,10 +305,10 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
317 * We shall invoke the user-defined callback function in the single 305 * We shall invoke the user-defined callback function in the single
318 * stepping handler to confirm to 'trigger-after-execute' semantics 306 * stepping handler to confirm to 'trigger-after-execute' semantics
319 */ 307 */
320 if (!info->extraneous_interrupt) 308 if (!(info->type & HW_BRK_TYPE_EXTRANEOUS_IRQ))
321 perf_bp_event(bp, regs); 309 perf_bp_event(bp, regs);
322 310
323 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx); 311 set_break(info);
324 current->thread.last_hit_ubp = NULL; 312 current->thread.last_hit_ubp = NULL;
325 313
326 /* 314 /*
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index c470a40b29f5..a05f0e4a9d38 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -198,7 +198,7 @@ static int kgdb_iabr_match(struct pt_regs *regs)
198 return 1; 198 return 1;
199} 199}
200 200
201static int kgdb_dabr_match(struct pt_regs *regs) 201static int kgdb_break_match(struct pt_regs *regs)
202{ 202{
203 if (user_mode(regs)) 203 if (user_mode(regs))
204 return 0; 204 return 0;
@@ -458,7 +458,7 @@ static void *old__debugger;
458static void *old__debugger_bpt; 458static void *old__debugger_bpt;
459static void *old__debugger_sstep; 459static void *old__debugger_sstep;
460static void *old__debugger_iabr_match; 460static void *old__debugger_iabr_match;
461static void *old__debugger_dabr_match; 461static void *old__debugger_break_match;
462static void *old__debugger_fault_handler; 462static void *old__debugger_fault_handler;
463 463
464int kgdb_arch_init(void) 464int kgdb_arch_init(void)
@@ -468,7 +468,7 @@ int kgdb_arch_init(void)
468 old__debugger_bpt = __debugger_bpt; 468 old__debugger_bpt = __debugger_bpt;
469 old__debugger_sstep = __debugger_sstep; 469 old__debugger_sstep = __debugger_sstep;
470 old__debugger_iabr_match = __debugger_iabr_match; 470 old__debugger_iabr_match = __debugger_iabr_match;
471 old__debugger_dabr_match = __debugger_dabr_match; 471 old__debugger_break_match = __debugger_break_match;
472 old__debugger_fault_handler = __debugger_fault_handler; 472 old__debugger_fault_handler = __debugger_fault_handler;
473 473
474 __debugger_ipi = kgdb_call_nmi_hook; 474 __debugger_ipi = kgdb_call_nmi_hook;
@@ -476,7 +476,7 @@ int kgdb_arch_init(void)
476 __debugger_bpt = kgdb_handle_breakpoint; 476 __debugger_bpt = kgdb_handle_breakpoint;
477 __debugger_sstep = kgdb_singlestep; 477 __debugger_sstep = kgdb_singlestep;
478 __debugger_iabr_match = kgdb_iabr_match; 478 __debugger_iabr_match = kgdb_iabr_match;
479 __debugger_dabr_match = kgdb_dabr_match; 479 __debugger_break_match = kgdb_break_match;
480 __debugger_fault_handler = kgdb_not_implemented; 480 __debugger_fault_handler = kgdb_not_implemented;
481 481
482 return 0; 482 return 0;
@@ -489,6 +489,6 @@ void kgdb_arch_exit(void)
489 __debugger_bpt = old__debugger_bpt; 489 __debugger_bpt = old__debugger_bpt;
490 __debugger_sstep = old__debugger_sstep; 490 __debugger_sstep = old__debugger_sstep;
491 __debugger_iabr_match = old__debugger_iabr_match; 491 __debugger_iabr_match = old__debugger_iabr_match;
492 __debugger_dabr_match = old__debugger_dabr_match; 492 __debugger_breakx_match = old__debugger_break_match;
493 __debugger_fault_handler = old__debugger_fault_handler; 493 __debugger_fault_handler = old__debugger_fault_handler;
494} 494}
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 3065d17f3606..c16c1c2abeea 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -271,7 +271,7 @@ void do_send_trap(struct pt_regs *regs, unsigned long address,
271 force_sig_info(SIGTRAP, &info, current); 271 force_sig_info(SIGTRAP, &info, current);
272} 272}
273#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ 273#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
274void do_dabr(struct pt_regs *regs, unsigned long address, 274void do_break (struct pt_regs *regs, unsigned long address,
275 unsigned long error_code) 275 unsigned long error_code)
276{ 276{
277 siginfo_t info; 277 siginfo_t info;
@@ -281,11 +281,11 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
281 11, SIGSEGV) == NOTIFY_STOP) 281 11, SIGSEGV) == NOTIFY_STOP)
282 return; 282 return;
283 283
284 if (debugger_dabr_match(regs)) 284 if (debugger_break_match(regs))
285 return; 285 return;
286 286
287 /* Clear the DABR */ 287 /* Clear the breakpoint */
288 set_dabr(0, 0); 288 hw_breakpoint_disable();
289 289
290 /* Deliver the signal to userspace */ 290 /* Deliver the signal to userspace */
291 info.si_signo = SIGTRAP; 291 info.si_signo = SIGTRAP;
@@ -296,7 +296,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
296} 296}
297#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 297#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
298 298
299static DEFINE_PER_CPU(unsigned long, current_dabr); 299static DEFINE_PER_CPU(struct arch_hw_breakpoint, current_brk);
300 300
301#ifdef CONFIG_PPC_ADV_DEBUG_REGS 301#ifdef CONFIG_PPC_ADV_DEBUG_REGS
302/* 302/*
@@ -364,39 +364,72 @@ static void switch_booke_debug_regs(struct thread_struct *new_thread)
364#ifndef CONFIG_HAVE_HW_BREAKPOINT 364#ifndef CONFIG_HAVE_HW_BREAKPOINT
365static void set_debug_reg_defaults(struct thread_struct *thread) 365static void set_debug_reg_defaults(struct thread_struct *thread)
366{ 366{
367 if (thread->dabr) { 367 thread->hw_brk.address = 0;
368 thread->dabr = 0; 368 thread->hw_brk.type = 0;
369 thread->dabrx = 0; 369 set_break(&thread->hw_brk);
370 set_dabr(0, 0);
371 }
372} 370}
373#endif /* !CONFIG_HAVE_HW_BREAKPOINT */ 371#endif /* !CONFIG_HAVE_HW_BREAKPOINT */
374#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 372#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
375 373
376int set_dabr(unsigned long dabr, unsigned long dabrx)
377{
378 __get_cpu_var(current_dabr) = dabr;
379
380 if (ppc_md.set_dabr)
381 return ppc_md.set_dabr(dabr, dabrx);
382
383 /* XXX should we have a CPU_FTR_HAS_DABR ? */
384#ifdef CONFIG_PPC_ADV_DEBUG_REGS 374#ifdef CONFIG_PPC_ADV_DEBUG_REGS
375static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
376{
385 mtspr(SPRN_DAC1, dabr); 377 mtspr(SPRN_DAC1, dabr);
386#ifdef CONFIG_PPC_47x 378#ifdef CONFIG_PPC_47x
387 isync(); 379 isync();
388#endif 380#endif
381 return 0;
382}
389#elif defined(CONFIG_PPC_BOOK3S) 383#elif defined(CONFIG_PPC_BOOK3S)
384static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
385{
390 mtspr(SPRN_DABR, dabr); 386 mtspr(SPRN_DABR, dabr);
391 mtspr(SPRN_DABRX, dabrx); 387 mtspr(SPRN_DABRX, dabrx);
392#endif
393 return 0; 388 return 0;
394} 389}
390#else
391static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
392{
393 return -EINVAL;
394}
395#endif
396
397static inline int set_dabr(struct arch_hw_breakpoint *brk)
398{
399 unsigned long dabr, dabrx;
400
401 dabr = brk->address | (brk->type & HW_BRK_TYPE_DABR);
402 dabrx = ((brk->type >> 3) & 0x7);
403
404 if (ppc_md.set_dabr)
405 return ppc_md.set_dabr(dabr, dabrx);
406
407 return __set_dabr(dabr, dabrx);
408}
409
410int set_break(struct arch_hw_breakpoint *brk)
411{
412 __get_cpu_var(current_brk) = *brk;
413
414 return set_dabr(brk);
415}
395 416
396#ifdef CONFIG_PPC64 417#ifdef CONFIG_PPC64
397DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); 418DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
398#endif 419#endif
399 420
421static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
422 struct arch_hw_breakpoint *b)
423{
424 if (a->address != b->address)
425 return false;
426 if (a->type != b->type)
427 return false;
428 if (a->len != b->len)
429 return false;
430 return true;
431}
432
400struct task_struct *__switch_to(struct task_struct *prev, 433struct task_struct *__switch_to(struct task_struct *prev,
401 struct task_struct *new) 434 struct task_struct *new)
402{ 435{
@@ -481,8 +514,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
481 * schedule DABR 514 * schedule DABR
482 */ 515 */
483#ifndef CONFIG_HAVE_HW_BREAKPOINT 516#ifndef CONFIG_HAVE_HW_BREAKPOINT
484 if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) 517 if (unlikely(hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk)))
485 set_dabr(new->thread.dabr, new->thread.dabrx); 518 set_break(&new->thread.hw_brk);
486#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 519#endif /* CONFIG_HAVE_HW_BREAKPOINT */
487#endif 520#endif
488 521
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index c4970004d44d..d4afcccf1238 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -905,6 +905,9 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
905 struct perf_event *bp; 905 struct perf_event *bp;
906 struct perf_event_attr attr; 906 struct perf_event_attr attr;
907#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 907#endif /* CONFIG_HAVE_HW_BREAKPOINT */
908#ifndef CONFIG_PPC_ADV_DEBUG_REGS
909 struct arch_hw_breakpoint hw_brk;
910#endif
908 911
909 /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). 912 /* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
910 * For embedded processors we support one DAC and no IAC's at the 913 * For embedded processors we support one DAC and no IAC's at the
@@ -931,14 +934,17 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
931 */ 934 */
932 935
933 /* Ensure breakpoint translation bit is set */ 936 /* Ensure breakpoint translation bit is set */
934 if (data && !(data & DABR_TRANSLATION)) 937 if (data && !(data & HW_BRK_TYPE_TRANSLATE))
935 return -EIO; 938 return -EIO;
939 hw_brk.address = data & (~HW_BRK_TYPE_DABR);
940 hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
941 hw_brk.len = 8;
936#ifdef CONFIG_HAVE_HW_BREAKPOINT 942#ifdef CONFIG_HAVE_HW_BREAKPOINT
937 if (ptrace_get_breakpoints(task) < 0) 943 if (ptrace_get_breakpoints(task) < 0)
938 return -ESRCH; 944 return -ESRCH;
939 945
940 bp = thread->ptrace_bps[0]; 946 bp = thread->ptrace_bps[0];
941 if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) { 947 if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) {
942 if (bp) { 948 if (bp) {
943 unregister_hw_breakpoint(bp); 949 unregister_hw_breakpoint(bp);
944 thread->ptrace_bps[0] = NULL; 950 thread->ptrace_bps[0] = NULL;
@@ -948,10 +954,8 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
948 } 954 }
949 if (bp) { 955 if (bp) {
950 attr = bp->attr; 956 attr = bp->attr;
951 attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN; 957 attr.bp_addr = hw_brk.address;
952 arch_bp_generic_fields(data & 958 arch_bp_generic_fields(hw_brk.type, &attr.bp_type);
953 (DABR_DATA_WRITE | DABR_DATA_READ),
954 &attr.bp_type);
955 959
956 /* Enable breakpoint */ 960 /* Enable breakpoint */
957 attr.disabled = false; 961 attr.disabled = false;
@@ -963,16 +967,15 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
963 } 967 }
964 thread->ptrace_bps[0] = bp; 968 thread->ptrace_bps[0] = bp;
965 ptrace_put_breakpoints(task); 969 ptrace_put_breakpoints(task);
966 thread->dabr = data; 970 thread->hw_brk = hw_brk;
967 thread->dabrx = DABRX_ALL;
968 return 0; 971 return 0;
969 } 972 }
970 973
971 /* Create a new breakpoint request if one doesn't exist already */ 974 /* Create a new breakpoint request if one doesn't exist already */
972 hw_breakpoint_init(&attr); 975 hw_breakpoint_init(&attr);
973 attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN; 976 attr.bp_addr = hw_brk.address;
974 arch_bp_generic_fields(data & (DABR_DATA_WRITE | DABR_DATA_READ), 977 arch_bp_generic_fields(hw_brk.type,
975 &attr.bp_type); 978 &attr.bp_type);
976 979
977 thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, 980 thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
978 ptrace_triggered, NULL, task); 981 ptrace_triggered, NULL, task);
@@ -985,10 +988,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
985 ptrace_put_breakpoints(task); 988 ptrace_put_breakpoints(task);
986 989
987#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 990#endif /* CONFIG_HAVE_HW_BREAKPOINT */
988 991 task->thread.hw_brk = hw_brk;
989 /* Move contents to the DABR register */
990 task->thread.dabr = data;
991 task->thread.dabrx = DABRX_ALL;
992#else /* CONFIG_PPC_ADV_DEBUG_REGS */ 992#else /* CONFIG_PPC_ADV_DEBUG_REGS */
993 /* As described above, it was assumed 3 bits were passed with the data 993 /* As described above, it was assumed 3 bits were passed with the data
994 * address, but we will assume only the mode bits will be passed 994 * address, but we will assume only the mode bits will be passed
@@ -1349,7 +1349,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
1349 struct perf_event_attr attr; 1349 struct perf_event_attr attr;
1350#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 1350#endif /* CONFIG_HAVE_HW_BREAKPOINT */
1351#ifndef CONFIG_PPC_ADV_DEBUG_REGS 1351#ifndef CONFIG_PPC_ADV_DEBUG_REGS
1352 unsigned long dabr; 1352 struct arch_hw_breakpoint brk;
1353#endif 1353#endif
1354 1354
1355 if (bp_info->version != 1) 1355 if (bp_info->version != 1)
@@ -1397,12 +1397,12 @@ static long ppc_set_hwdebug(struct task_struct *child,
1397 if ((unsigned long)bp_info->addr >= TASK_SIZE) 1397 if ((unsigned long)bp_info->addr >= TASK_SIZE)
1398 return -EIO; 1398 return -EIO;
1399 1399
1400 dabr = (unsigned long)bp_info->addr & ~7UL; 1400 brk.address = bp_info->addr & ~7UL;
1401 dabr |= DABR_TRANSLATION; 1401 brk.type = HW_BRK_TYPE_TRANSLATE;
1402 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 1402 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
1403 dabr |= DABR_DATA_READ; 1403 brk.type |= HW_BRK_TYPE_READ;
1404 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 1404 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
1405 dabr |= DABR_DATA_WRITE; 1405 brk.type |= HW_BRK_TYPE_WRITE;
1406#ifdef CONFIG_HAVE_HW_BREAKPOINT 1406#ifdef CONFIG_HAVE_HW_BREAKPOINT
1407 if (ptrace_get_breakpoints(child) < 0) 1407 if (ptrace_get_breakpoints(child) < 0)
1408 return -ESRCH; 1408 return -ESRCH;
@@ -1427,8 +1427,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
1427 hw_breakpoint_init(&attr); 1427 hw_breakpoint_init(&attr);
1428 attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN; 1428 attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN;
1429 attr.bp_len = len; 1429 attr.bp_len = len;
1430 arch_bp_generic_fields(dabr & (DABR_DATA_WRITE | DABR_DATA_READ), 1430 arch_bp_generic_fields(brk.type, &attr.bp_type);
1431 &attr.bp_type);
1432 1431
1433 thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, 1432 thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
1434 ptrace_triggered, NULL, child); 1433 ptrace_triggered, NULL, child);
@@ -1445,11 +1444,10 @@ static long ppc_set_hwdebug(struct task_struct *child,
1445 if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) 1444 if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT)
1446 return -EINVAL; 1445 return -EINVAL;
1447 1446
1448 if (child->thread.dabr) 1447 if (child->thread.hw_brk.address)
1449 return -ENOSPC; 1448 return -ENOSPC;
1450 1449
1451 child->thread.dabr = dabr; 1450 child->thread.hw_brk = brk;
1452 child->thread.dabrx = DABRX_ALL;
1453 1451
1454 return 1; 1452 return 1;
1455#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ 1453#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
@@ -1495,10 +1493,11 @@ static long ppc_del_hwdebug(struct task_struct *child, long data)
1495 ptrace_put_breakpoints(child); 1493 ptrace_put_breakpoints(child);
1496 return ret; 1494 return ret;
1497#else /* CONFIG_HAVE_HW_BREAKPOINT */ 1495#else /* CONFIG_HAVE_HW_BREAKPOINT */
1498 if (child->thread.dabr == 0) 1496 if (child->thread.hw_brk.address == 0)
1499 return -ENOENT; 1497 return -ENOENT;
1500 1498
1501 child->thread.dabr = 0; 1499 child->thread.hw_brk.address = 0;
1500 child->thread.hw_brk.type = 0;
1502#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 1501#endif /* CONFIG_HAVE_HW_BREAKPOINT */
1503 1502
1504 return 0; 1503 return 0;
@@ -1642,6 +1641,9 @@ long arch_ptrace(struct task_struct *child, long request,
1642 } 1641 }
1643 1642
1644 case PTRACE_GET_DEBUGREG: { 1643 case PTRACE_GET_DEBUGREG: {
1644#ifndef CONFIG_PPC_ADV_DEBUG_REGS
1645 unsigned long dabr_fake;
1646#endif
1645 ret = -EINVAL; 1647 ret = -EINVAL;
1646 /* We only support one DABR and no IABRS at the moment */ 1648 /* We only support one DABR and no IABRS at the moment */
1647 if (addr > 0) 1649 if (addr > 0)
@@ -1649,7 +1651,9 @@ long arch_ptrace(struct task_struct *child, long request,
1649#ifdef CONFIG_PPC_ADV_DEBUG_REGS 1651#ifdef CONFIG_PPC_ADV_DEBUG_REGS
1650 ret = put_user(child->thread.dac1, datalp); 1652 ret = put_user(child->thread.dac1, datalp);
1651#else 1653#else
1652 ret = put_user(child->thread.dabr, datalp); 1654 dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) |
1655 (child->thread.hw_brk.type & HW_BRK_TYPE_DABR));
1656 ret = put_user(dabr_fake, datalp);
1653#endif 1657#endif
1654 break; 1658 break;
1655 } 1659 }
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 8c21658719d9..c0244e766834 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -252,6 +252,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
252 } 252 }
253 253
254 case PTRACE_GET_DEBUGREG: { 254 case PTRACE_GET_DEBUGREG: {
255#ifndef CONFIG_PPC_ADV_DEBUG_REGS
256 unsigned long dabr_fake;
257#endif
255 ret = -EINVAL; 258 ret = -EINVAL;
256 /* We only support one DABR and no IABRS at the moment */ 259 /* We only support one DABR and no IABRS at the moment */
257 if (addr > 0) 260 if (addr > 0)
@@ -259,7 +262,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
259#ifdef CONFIG_PPC_ADV_DEBUG_REGS 262#ifdef CONFIG_PPC_ADV_DEBUG_REGS
260 ret = put_user(child->thread.dac1, (u32 __user *)data); 263 ret = put_user(child->thread.dac1, (u32 __user *)data);
261#else 264#else
262 ret = put_user(child->thread.dabr, (u32 __user *)data); 265 dabr_fake = (
266 (child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) |
267 (child->thread.hw_brk.type & HW_BRK_TYPE_DABR));
268 ret = put_user(dabr_fake, (u32 __user *)data);
263#endif 269#endif
264 break; 270 break;
265 } 271 }
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 3b997118df50..1f26956d3913 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -130,8 +130,9 @@ static int do_signal(struct pt_regs *regs)
130 * user space. The DABR will have been cleared if it 130 * user space. The DABR will have been cleared if it
131 * triggered inside the kernel. 131 * triggered inside the kernel.
132 */ 132 */
133 if (current->thread.dabr) 133 if (current->thread.hw_brk.address &&
134 set_dabr(current->thread.dabr, current->thread.dabrx); 134 current->thread.hw_brk.type)
135 set_break(&current->thread.hw_brk);
135#endif 136#endif
136 /* Re-enable the breakpoints for the signal stack */ 137 /* Re-enable the breakpoints for the signal stack */
137 thread_change_pc(current, regs); 138 thread_change_pc(current, regs);
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 114ea241916f..a008cf5c0fce 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -66,7 +66,7 @@ int (*__debugger_ipi)(struct pt_regs *regs) __read_mostly;
66int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly; 66int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly;
67int (*__debugger_sstep)(struct pt_regs *regs) __read_mostly; 67int (*__debugger_sstep)(struct pt_regs *regs) __read_mostly;
68int (*__debugger_iabr_match)(struct pt_regs *regs) __read_mostly; 68int (*__debugger_iabr_match)(struct pt_regs *regs) __read_mostly;
69int (*__debugger_dabr_match)(struct pt_regs *regs) __read_mostly; 69int (*__debugger_break_match)(struct pt_regs *regs) __read_mostly;
70int (*__debugger_fault_handler)(struct pt_regs *regs) __read_mostly; 70int (*__debugger_fault_handler)(struct pt_regs *regs) __read_mostly;
71 71
72EXPORT_SYMBOL(__debugger); 72EXPORT_SYMBOL(__debugger);
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(__debugger_ipi);
74EXPORT_SYMBOL(__debugger_bpt); 74EXPORT_SYMBOL(__debugger_bpt);
75EXPORT_SYMBOL(__debugger_sstep); 75EXPORT_SYMBOL(__debugger_sstep);
76EXPORT_SYMBOL(__debugger_iabr_match); 76EXPORT_SYMBOL(__debugger_iabr_match);
77EXPORT_SYMBOL(__debugger_dabr_match); 77EXPORT_SYMBOL(__debugger_break_match);
78EXPORT_SYMBOL(__debugger_fault_handler); 78EXPORT_SYMBOL(__debugger_fault_handler);
79#endif 79#endif
80 80
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 3a8489a354e9..229951ffc351 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -249,8 +249,8 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
249#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE) || \ 249#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE) || \
250 defined(CONFIG_PPC_BOOK3S_64)) 250 defined(CONFIG_PPC_BOOK3S_64))
251 if (error_code & DSISR_DABRMATCH) { 251 if (error_code & DSISR_DABRMATCH) {
252 /* DABR match */ 252 /* breakpoint match */
253 do_dabr(regs, address, error_code); 253 do_break(regs, address, error_code);
254 return 0; 254 return 0;
255 } 255 }
256#endif 256#endif
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 1f8d2f10a432..529c1ed7f59f 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -43,6 +43,7 @@
43#include <asm/setjmp.h> 43#include <asm/setjmp.h>
44#include <asm/reg.h> 44#include <asm/reg.h>
45#include <asm/debug.h> 45#include <asm/debug.h>
46#include <asm/hw_breakpoint.h>
46 47
47#ifdef CONFIG_PPC64 48#ifdef CONFIG_PPC64
48#include <asm/hvcall.h> 49#include <asm/hvcall.h>
@@ -607,7 +608,7 @@ static int xmon_sstep(struct pt_regs *regs)
607 return 1; 608 return 1;
608} 609}
609 610
610static int xmon_dabr_match(struct pt_regs *regs) 611static int xmon_break_match(struct pt_regs *regs)
611{ 612{
612 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT)) 613 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
613 return 0; 614 return 0;
@@ -740,8 +741,14 @@ static void insert_bpts(void)
740 741
741static void insert_cpu_bpts(void) 742static void insert_cpu_bpts(void)
742{ 743{
743 if (dabr.enabled) 744 struct arch_hw_breakpoint brk;
744 set_dabr(dabr.address | (dabr.enabled & 7), DABRX_ALL); 745
746 if (dabr.enabled) {
747 brk.address = dabr.address;
748 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
749 brk.len = 8;
750 set_break(&brk);
751 }
745 if (iabr && cpu_has_feature(CPU_FTR_IABR)) 752 if (iabr && cpu_has_feature(CPU_FTR_IABR))
746 mtspr(SPRN_IABR, iabr->address 753 mtspr(SPRN_IABR, iabr->address
747 | (iabr->enabled & (BP_IABR|BP_IABR_TE))); 754 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -769,7 +776,7 @@ static void remove_bpts(void)
769 776
770static void remove_cpu_bpts(void) 777static void remove_cpu_bpts(void)
771{ 778{
772 set_dabr(0, 0); 779 hw_breakpoint_disable();
773 if (cpu_has_feature(CPU_FTR_IABR)) 780 if (cpu_has_feature(CPU_FTR_IABR))
774 mtspr(SPRN_IABR, 0); 781 mtspr(SPRN_IABR, 0);
775} 782}
@@ -1138,7 +1145,7 @@ bpt_cmds(void)
1138 printf(badaddr); 1145 printf(badaddr);
1139 break; 1146 break;
1140 } 1147 }
1141 dabr.address &= ~7; 1148 dabr.address &= ~HW_BRK_TYPE_DABR;
1142 dabr.enabled = mode | BP_DABR; 1149 dabr.enabled = mode | BP_DABR;
1143 } 1150 }
1144 break; 1151 break;
@@ -2917,7 +2924,7 @@ static void xmon_init(int enable)
2917 __debugger_bpt = xmon_bpt; 2924 __debugger_bpt = xmon_bpt;
2918 __debugger_sstep = xmon_sstep; 2925 __debugger_sstep = xmon_sstep;
2919 __debugger_iabr_match = xmon_iabr_match; 2926 __debugger_iabr_match = xmon_iabr_match;
2920 __debugger_dabr_match = xmon_dabr_match; 2927 __debugger_break_match = xmon_break_match;
2921 __debugger_fault_handler = xmon_fault_handler; 2928 __debugger_fault_handler = xmon_fault_handler;
2922 } else { 2929 } else {
2923 __debugger = NULL; 2930 __debugger = NULL;
@@ -2925,7 +2932,7 @@ static void xmon_init(int enable)
2925 __debugger_bpt = NULL; 2932 __debugger_bpt = NULL;
2926 __debugger_sstep = NULL; 2933 __debugger_sstep = NULL;
2927 __debugger_iabr_match = NULL; 2934 __debugger_iabr_match = NULL;
2928 __debugger_dabr_match = NULL; 2935 __debugger_break_match = NULL;
2929 __debugger_fault_handler = NULL; 2936 __debugger_fault_handler = NULL;
2930 } 2937 }
2931} 2938}