aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r--arch/powerpc/kernel/process.c116
1 files changed, 96 insertions, 20 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7b816daf3eba..e4d71ced97ef 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -245,6 +245,24 @@ void discard_lazy_cpu_state(void)
245} 245}
246#endif /* CONFIG_SMP */ 246#endif /* CONFIG_SMP */
247 247
248#ifdef CONFIG_PPC_ADV_DEBUG_REGS
249void do_send_trap(struct pt_regs *regs, unsigned long address,
250 unsigned long error_code, int signal_code, int breakpt)
251{
252 siginfo_t info;
253
254 if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
255 11, SIGSEGV) == NOTIFY_STOP)
256 return;
257
258 /* Deliver the signal to userspace */
259 info.si_signo = SIGTRAP;
260 info.si_errno = breakpt; /* breakpoint or watchpoint id */
261 info.si_code = signal_code;
262 info.si_addr = (void __user *)address;
263 force_sig_info(SIGTRAP, &info, current);
264}
265#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
248void do_dabr(struct pt_regs *regs, unsigned long address, 266void do_dabr(struct pt_regs *regs, unsigned long address,
249 unsigned long error_code) 267 unsigned long error_code)
250{ 268{
@@ -257,12 +275,6 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
257 if (debugger_dabr_match(regs)) 275 if (debugger_dabr_match(regs))
258 return; 276 return;
259 277
260 /* Clear the DAC and struct entries. One shot trigger */
261#if defined(CONFIG_BOOKE)
262 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
263 | DBCR0_IDM));
264#endif
265
266 /* Clear the DABR */ 278 /* Clear the DABR */
267 set_dabr(0); 279 set_dabr(0);
268 280
@@ -273,9 +285,82 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
273 info.si_addr = (void __user *)address; 285 info.si_addr = (void __user *)address;
274 force_sig_info(SIGTRAP, &info, current); 286 force_sig_info(SIGTRAP, &info, current);
275} 287}
288#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
276 289
277static DEFINE_PER_CPU(unsigned long, current_dabr); 290static DEFINE_PER_CPU(unsigned long, current_dabr);
278 291
292#ifdef CONFIG_PPC_ADV_DEBUG_REGS
293/*
294 * Set the debug registers back to their default "safe" values.
295 */
296static void set_debug_reg_defaults(struct thread_struct *thread)
297{
298 thread->iac1 = thread->iac2 = 0;
299#if CONFIG_PPC_ADV_DEBUG_IACS > 2
300 thread->iac3 = thread->iac4 = 0;
301#endif
302 thread->dac1 = thread->dac2 = 0;
303#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
304 thread->dvc1 = thread->dvc2 = 0;
305#endif
306 thread->dbcr0 = 0;
307#ifdef CONFIG_BOOKE
308 /*
309 * Force User/Supervisor bits to b11 (user-only MSR[PR]=1)
310 */
311 thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | \
312 DBCR1_IAC3US | DBCR1_IAC4US;
313 /*
314 * Force Data Address Compare User/Supervisor bits to be User-only
315 * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0.
316 */
317 thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US;
318#else
319 thread->dbcr1 = 0;
320#endif
321}
322
323static void prime_debug_regs(struct thread_struct *thread)
324{
325 mtspr(SPRN_IAC1, thread->iac1);
326 mtspr(SPRN_IAC2, thread->iac2);
327#if CONFIG_PPC_ADV_DEBUG_IACS > 2
328 mtspr(SPRN_IAC3, thread->iac3);
329 mtspr(SPRN_IAC4, thread->iac4);
330#endif
331 mtspr(SPRN_DAC1, thread->dac1);
332 mtspr(SPRN_DAC2, thread->dac2);
333#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
334 mtspr(SPRN_DVC1, thread->dvc1);
335 mtspr(SPRN_DVC2, thread->dvc2);
336#endif
337 mtspr(SPRN_DBCR0, thread->dbcr0);
338 mtspr(SPRN_DBCR1, thread->dbcr1);
339#ifdef CONFIG_BOOKE
340 mtspr(SPRN_DBCR2, thread->dbcr2);
341#endif
342}
343/*
344 * Unless neither the old or new thread are making use of the
345 * debug registers, set the debug registers from the values
346 * stored in the new thread.
347 */
348static void switch_booke_debug_regs(struct thread_struct *new_thread)
349{
350 if ((current->thread.dbcr0 & DBCR0_IDM)
351 || (new_thread->dbcr0 & DBCR0_IDM))
352 prime_debug_regs(new_thread);
353}
354#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
355static void set_debug_reg_defaults(struct thread_struct *thread)
356{
357 if (thread->dabr) {
358 thread->dabr = 0;
359 set_dabr(0);
360 }
361}
362#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
363
279int set_dabr(unsigned long dabr) 364int set_dabr(unsigned long dabr)
280{ 365{
281 __get_cpu_var(current_dabr) = dabr; 366 __get_cpu_var(current_dabr) = dabr;
@@ -284,7 +369,7 @@ int set_dabr(unsigned long dabr)
284 return ppc_md.set_dabr(dabr); 369 return ppc_md.set_dabr(dabr);
285 370
286 /* XXX should we have a CPU_FTR_HAS_DABR ? */ 371 /* XXX should we have a CPU_FTR_HAS_DABR ? */
287#if defined(CONFIG_BOOKE) 372#ifdef CONFIG_PPC_ADV_DEBUG_REGS
288 mtspr(SPRN_DAC1, dabr); 373 mtspr(SPRN_DAC1, dabr);
289#elif defined(CONFIG_PPC_BOOK3S) 374#elif defined(CONFIG_PPC_BOOK3S)
290 mtspr(SPRN_DABR, dabr); 375 mtspr(SPRN_DABR, dabr);
@@ -371,10 +456,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
371 456
372#endif /* CONFIG_SMP */ 457#endif /* CONFIG_SMP */
373 458
374#if defined(CONFIG_BOOKE) 459#ifdef CONFIG_PPC_ADV_DEBUG_REGS
375 /* If new thread DAC (HW breakpoint) is the same then leave it */ 460 switch_booke_debug_regs(&new->thread);
376 if (new->thread.dabr)
377 set_dabr(new->thread.dabr);
378#else 461#else
379 if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) 462 if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
380 set_dabr(new->thread.dabr); 463 set_dabr(new->thread.dabr);
@@ -514,7 +597,7 @@ void show_regs(struct pt_regs * regs)
514 printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); 597 printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
515 trap = TRAP(regs); 598 trap = TRAP(regs);
516 if (trap == 0x300 || trap == 0x600) 599 if (trap == 0x300 || trap == 0x600)
517#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) 600#ifdef CONFIG_PPC_ADV_DEBUG_REGS
518 printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr); 601 printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
519#else 602#else
520 printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); 603 printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
@@ -556,14 +639,7 @@ void flush_thread(void)
556{ 639{
557 discard_lazy_cpu_state(); 640 discard_lazy_cpu_state();
558 641
559 if (current->thread.dabr) { 642 set_debug_reg_defaults(&current->thread);
560 current->thread.dabr = 0;
561 set_dabr(0);
562
563#if defined(CONFIG_BOOKE)
564 current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
565#endif
566 }
567} 643}
568 644
569void 645void