aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/debug.h2
-rw-r--r--arch/powerpc/include/asm/hw_breakpoint.h2
-rw-r--r--arch/powerpc/include/asm/machdep.h3
-rw-r--r--arch/powerpc/include/asm/processor.h1
-rw-r--r--arch/powerpc/include/asm/reg.h3
-rw-r--r--arch/powerpc/kernel/hw_breakpoint.c12
-rw-r--r--arch/powerpc/kernel/process.c14
-rw-r--r--arch/powerpc/kernel/ptrace.c3
-rw-r--r--arch/powerpc/kernel/signal.c2
-rw-r--r--arch/powerpc/platforms/cell/beat.c4
-rw-r--r--arch/powerpc/platforms/cell/beat.h2
-rw-r--r--arch/powerpc/platforms/ps3/setup.c10
-rw-r--r--arch/powerpc/platforms/pseries/setup.c14
-rw-r--r--arch/powerpc/xmon/xmon.c4
14 files changed, 46 insertions, 30 deletions
diff --git a/arch/powerpc/include/asm/debug.h b/arch/powerpc/include/asm/debug.h
index 716d2f089eb6..32de2577bb6d 100644
--- a/arch/powerpc/include/asm/debug.h
+++ b/arch/powerpc/include/asm/debug.h
@@ -44,7 +44,7 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
44static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } 44static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
45#endif 45#endif
46 46
47extern int set_dabr(unsigned long dabr); 47extern int set_dabr(unsigned long dabr, unsigned long dabrx);
48#ifdef CONFIG_PPC_ADV_DEBUG_REGS 48#ifdef CONFIG_PPC_ADV_DEBUG_REGS
49extern void do_send_trap(struct pt_regs *regs, unsigned long address, 49extern void do_send_trap(struct pt_regs *regs, unsigned long address,
50 unsigned long error_code, int signal_code, int brkpt); 50 unsigned long error_code, int signal_code, int brkpt);
diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h
index 39b323e80c30..c6f48eb5299c 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -61,7 +61,7 @@ extern void ptrace_triggered(struct perf_event *bp,
61 struct perf_sample_data *data, struct pt_regs *regs); 61 struct perf_sample_data *data, struct pt_regs *regs);
62static inline void hw_breakpoint_disable(void) 62static inline void hw_breakpoint_disable(void)
63{ 63{
64 set_dabr(0); 64 set_dabr(0, 0);
65} 65}
66extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs); 66extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
67 67
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 42ce570812c1..236b4779ec4f 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -180,7 +180,8 @@ struct machdep_calls {
180 void (*enable_pmcs)(void); 180 void (*enable_pmcs)(void);
181 181
182 /* Set DABR for this platform, leave empty for default implemenation */ 182 /* Set DABR for this platform, leave empty for default implemenation */
183 int (*set_dabr)(unsigned long dabr); 183 int (*set_dabr)(unsigned long dabr,
184 unsigned long dabrx);
184 185
185#ifdef CONFIG_PPC32 /* XXX for now */ 186#ifdef CONFIG_PPC32 /* XXX for now */
186 /* A general init function, called by ppc_init in init/main.c. 187 /* A general init function, called by ppc_init in init/main.c.
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 7e7fa13e4667..83efc6e81543 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -219,6 +219,7 @@ struct thread_struct {
219#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 219#endif /* CONFIG_HAVE_HW_BREAKPOINT */
220#endif 220#endif
221 unsigned long dabr; /* Data address breakpoint register */ 221 unsigned long dabr; /* Data address breakpoint register */
222 unsigned long dabrx; /* ... extension */
222 unsigned long trap_nr; /* last trap # on this thread */ 223 unsigned long trap_nr; /* last trap # on this thread */
223#ifdef CONFIG_ALTIVEC 224#ifdef CONFIG_ALTIVEC
224 /* Complete AltiVec register set */ 225 /* Complete AltiVec register set */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index ad400a535d23..121a90bbf778 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -208,6 +208,9 @@
208#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */ 208#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */
209#define DABRX_USER (1UL << 0) 209#define DABRX_USER (1UL << 0)
210#define DABRX_KERNEL (1UL << 1) 210#define DABRX_KERNEL (1UL << 1)
211#define DABRX_HYP (1UL << 2)
212#define DABRX_BTI (1UL << 3)
213#define DABRX_ALL (DABRX_BTI | DABRX_HYP | DABRX_KERNEL | DABRX_USER)
211#define SPRN_DAR 0x013 /* Data Address Register */ 214#define SPRN_DAR 0x013 /* Data Address Register */
212#define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */ 215#define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */
213#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ 216#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 6767445ecb45..6891d79ecef6 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); 76 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL);
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); 100 set_dabr(0, 0);
101} 101}
102 102
103/* 103/*
@@ -197,7 +197,7 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
197 197
198 info = counter_arch_bp(tsk->thread.last_hit_ubp); 198 info = counter_arch_bp(tsk->thread.last_hit_ubp);
199 regs->msr &= ~MSR_SE; 199 regs->msr &= ~MSR_SE;
200 set_dabr(info->address | info->type | DABR_TRANSLATION); 200 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL);
201 tsk->thread.last_hit_ubp = NULL; 201 tsk->thread.last_hit_ubp = NULL;
202} 202}
203 203
@@ -215,7 +215,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
215 unsigned long dar = regs->dar; 215 unsigned long dar = regs->dar;
216 216
217 /* Disable breakpoints during exception handling */ 217 /* Disable breakpoints during exception handling */
218 set_dabr(0); 218 set_dabr(0, 0);
219 219
220 /* 220 /*
221 * The counter may be concurrently released but that can only 221 * The counter may be concurrently released but that can only
@@ -281,7 +281,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
281 if (!info->extraneous_interrupt) 281 if (!info->extraneous_interrupt)
282 perf_bp_event(bp, regs); 282 perf_bp_event(bp, regs);
283 283
284 set_dabr(info->address | info->type | DABR_TRANSLATION); 284 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL);
285out: 285out:
286 rcu_read_unlock(); 286 rcu_read_unlock();
287 return rc; 287 return rc;
@@ -313,7 +313,7 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
313 if (!info->extraneous_interrupt) 313 if (!info->extraneous_interrupt)
314 perf_bp_event(bp, regs); 314 perf_bp_event(bp, regs);
315 315
316 set_dabr(info->address | info->type | DABR_TRANSLATION); 316 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL);
317 current->thread.last_hit_ubp = NULL; 317 current->thread.last_hit_ubp = NULL;
318 318
319 /* 319 /*
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2e743de545d0..50e504c29bb9 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -285,7 +285,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
285 return; 285 return;
286 286
287 /* Clear the DABR */ 287 /* Clear the DABR */
288 set_dabr(0); 288 set_dabr(0, 0);
289 289
290 /* Deliver the signal to userspace */ 290 /* Deliver the signal to userspace */
291 info.si_signo = SIGTRAP; 291 info.si_signo = SIGTRAP;
@@ -366,18 +366,19 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
366{ 366{
367 if (thread->dabr) { 367 if (thread->dabr) {
368 thread->dabr = 0; 368 thread->dabr = 0;
369 set_dabr(0); 369 thread->dabrx = 0;
370 set_dabr(0, 0);
370 } 371 }
371} 372}
372#endif /* !CONFIG_HAVE_HW_BREAKPOINT */ 373#endif /* !CONFIG_HAVE_HW_BREAKPOINT */
373#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 374#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
374 375
375int set_dabr(unsigned long dabr) 376int set_dabr(unsigned long dabr, unsigned long dabrx)
376{ 377{
377 __get_cpu_var(current_dabr) = dabr; 378 __get_cpu_var(current_dabr) = dabr;
378 379
379 if (ppc_md.set_dabr) 380 if (ppc_md.set_dabr)
380 return ppc_md.set_dabr(dabr); 381 return ppc_md.set_dabr(dabr, dabrx);
381 382
382 /* XXX should we have a CPU_FTR_HAS_DABR ? */ 383 /* XXX should we have a CPU_FTR_HAS_DABR ? */
383#ifdef CONFIG_PPC_ADV_DEBUG_REGS 384#ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -387,9 +388,8 @@ int set_dabr(unsigned long dabr)
387#endif 388#endif
388#elif defined(CONFIG_PPC_BOOK3S) 389#elif defined(CONFIG_PPC_BOOK3S)
389 mtspr(SPRN_DABR, dabr); 390 mtspr(SPRN_DABR, dabr);
391 mtspr(SPRN_DABRX, dabrx);
390#endif 392#endif
391
392
393 return 0; 393 return 0;
394} 394}
395 395
@@ -482,7 +482,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
482 */ 482 */
483#ifndef CONFIG_HAVE_HW_BREAKPOINT 483#ifndef CONFIG_HAVE_HW_BREAKPOINT
484 if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) 484 if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
485 set_dabr(new->thread.dabr); 485 set_dabr(new->thread.dabr, new->thread.dabrx);
486#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 486#endif /* CONFIG_HAVE_HW_BREAKPOINT */
487#endif 487#endif
488 488
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index c10fc28b9092..79d8e56470df 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -960,6 +960,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
960 thread->ptrace_bps[0] = bp; 960 thread->ptrace_bps[0] = bp;
961 ptrace_put_breakpoints(task); 961 ptrace_put_breakpoints(task);
962 thread->dabr = data; 962 thread->dabr = data;
963 thread->dabrx = DABRX_ALL;
963 return 0; 964 return 0;
964 } 965 }
965 966
@@ -983,6 +984,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
983 984
984 /* Move contents to the DABR register */ 985 /* Move contents to the DABR register */
985 task->thread.dabr = data; 986 task->thread.dabr = data;
987 task->thread.dabrx = DABRX_ALL;
986#else /* CONFIG_PPC_ADV_DEBUG_REGS */ 988#else /* CONFIG_PPC_ADV_DEBUG_REGS */
987 /* As described above, it was assumed 3 bits were passed with the data 989 /* As described above, it was assumed 3 bits were passed with the data
988 * address, but we will assume only the mode bits will be passed 990 * address, but we will assume only the mode bits will be passed
@@ -1397,6 +1399,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
1397 dabr |= DABR_DATA_WRITE; 1399 dabr |= DABR_DATA_WRITE;
1398 1400
1399 child->thread.dabr = dabr; 1401 child->thread.dabr = dabr;
1402 child->thread.dabrx = DABRX_ALL;
1400 1403
1401 return 1; 1404 return 1;
1402#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ 1405#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 29be2712e560..a2dc75793bd5 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -131,7 +131,7 @@ static int do_signal(struct pt_regs *regs)
131 * triggered inside the kernel. 131 * triggered inside the kernel.
132 */ 132 */
133 if (current->thread.dabr) 133 if (current->thread.dabr)
134 set_dabr(current->thread.dabr); 134 set_dabr(current->thread.dabr, current->thread.dabrx);
135#endif 135#endif
136 /* Re-enable the breakpoints for the signal stack */ 136 /* Re-enable the breakpoints for the signal stack */
137 thread_change_pc(current, regs); 137 thread_change_pc(current, regs);
diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c
index 852592b2b712..affcf566d460 100644
--- a/arch/powerpc/platforms/cell/beat.c
+++ b/arch/powerpc/platforms/cell/beat.c
@@ -136,9 +136,9 @@ ssize_t beat_nvram_get_size(void)
136 return BEAT_NVRAM_SIZE; 136 return BEAT_NVRAM_SIZE;
137} 137}
138 138
139int beat_set_xdabr(unsigned long dabr) 139int beat_set_xdabr(unsigned long dabr, unsigned long dabrx)
140{ 140{
141 if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER)) 141 if (beat_set_dabr(dabr, dabrx))
142 return -1; 142 return -1;
143 return 0; 143 return 0;
144} 144}
diff --git a/arch/powerpc/platforms/cell/beat.h b/arch/powerpc/platforms/cell/beat.h
index 32c8efcedc80..bfcb8e351ae5 100644
--- a/arch/powerpc/platforms/cell/beat.h
+++ b/arch/powerpc/platforms/cell/beat.h
@@ -32,7 +32,7 @@ void beat_get_rtc_time(struct rtc_time *);
32ssize_t beat_nvram_get_size(void); 32ssize_t beat_nvram_get_size(void);
33ssize_t beat_nvram_read(char *, size_t, loff_t *); 33ssize_t beat_nvram_read(char *, size_t, loff_t *);
34ssize_t beat_nvram_write(char *, size_t, loff_t *); 34ssize_t beat_nvram_write(char *, size_t, loff_t *);
35int beat_set_xdabr(unsigned long); 35int beat_set_xdabr(unsigned long, unsigned long);
36void beat_power_save(void); 36void beat_power_save(void);
37void beat_kexec_cpu_down(int, int); 37void beat_kexec_cpu_down(int, int);
38 38
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 2d664c5a83b0..3f509f86432c 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -184,11 +184,15 @@ early_param("ps3flash", early_parse_ps3flash);
184#define prealloc_ps3flash_bounce_buffer() do { } while (0) 184#define prealloc_ps3flash_bounce_buffer() do { } while (0)
185#endif 185#endif
186 186
187static int ps3_set_dabr(unsigned long dabr) 187static int ps3_set_dabr(unsigned long dabr, unsigned long dabrx)
188{ 188{
189 enum {DABR_USER = 1, DABR_KERNEL = 2,}; 189 /* Have to set at least one bit in the DABRX */
190 if (dabrx == 0 && dabr == 0)
191 dabrx = DABRX_USER;
192 /* hypervisor only allows us to set BTI, Kernel and user */
193 dabrx &= DABRX_BTI | DABRX_KERNEL | DABRX_USER;
190 194
191 return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0; 195 return lv1_set_dabr(dabr, dabrx) ? -1 : 0;
192} 196}
193 197
194static void __init ps3_setup_arch(void) 198static void __init ps3_setup_arch(void)
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 4a2cd48b21f6..a3a69658a6ec 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -414,16 +414,20 @@ static int __init pSeries_init_panel(void)
414} 414}
415machine_arch_initcall(pseries, pSeries_init_panel); 415machine_arch_initcall(pseries, pSeries_init_panel);
416 416
417static int pseries_set_dabr(unsigned long dabr) 417static int pseries_set_dabr(unsigned long dabr, unsigned long dabrx)
418{ 418{
419 return plpar_hcall_norets(H_SET_DABR, dabr); 419 return plpar_hcall_norets(H_SET_DABR, dabr);
420} 420}
421 421
422static int pseries_set_xdabr(unsigned long dabr) 422static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx)
423{ 423{
424 /* We want to catch accesses from kernel and userspace */ 424 /* Have to set at least one bit in the DABRX according to PAPR */
425 return plpar_hcall_norets(H_SET_XDABR, dabr, 425 if (dabrx == 0 && dabr == 0)
426 H_DABRX_KERNEL | H_DABRX_USER); 426 dabrx = DABRX_USER;
427 /* PAPR says we can only set kernel and user bits */
428 dabrx &= H_DABRX_KERNEL | H_DABRX_USER;
429
430 return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx);
427} 431}
428 432
429#define CMO_CHARACTERISTICS_TOKEN 44 433#define CMO_CHARACTERISTICS_TOKEN 44
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 9b49c65ee7a4..987f441525cb 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -740,7 +740,7 @@ static void insert_bpts(void)
740static void insert_cpu_bpts(void) 740static void insert_cpu_bpts(void)
741{ 741{
742 if (dabr.enabled) 742 if (dabr.enabled)
743 set_dabr(dabr.address | (dabr.enabled & 7)); 743 set_dabr(dabr.address | (dabr.enabled & 7), DABRX_ALL);
744 if (iabr && cpu_has_feature(CPU_FTR_IABR)) 744 if (iabr && cpu_has_feature(CPU_FTR_IABR))
745 mtspr(SPRN_IABR, iabr->address 745 mtspr(SPRN_IABR, iabr->address
746 | (iabr->enabled & (BP_IABR|BP_IABR_TE))); 746 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -768,7 +768,7 @@ static void remove_bpts(void)
768 768
769static void remove_cpu_bpts(void) 769static void remove_cpu_bpts(void)
770{ 770{
771 set_dabr(0); 771 set_dabr(0, 0);
772 if (cpu_has_feature(CPU_FTR_IABR)) 772 if (cpu_has_feature(CPU_FTR_IABR))
773 mtspr(SPRN_IABR, 0); 773 mtspr(SPRN_IABR, 0);
774} 774}