diff options
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r-- | arch/powerpc/kernel/process.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 773424df828a..551f6713ff42 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
38 | #include <linux/personality.h> | 38 | #include <linux/personality.h> |
39 | #include <linux/random.h> | 39 | #include <linux/random.h> |
40 | #include <linux/hw_breakpoint.h> | ||
40 | 41 | ||
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
@@ -462,14 +463,42 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
462 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 463 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
463 | switch_booke_debug_regs(&new->thread); | 464 | switch_booke_debug_regs(&new->thread); |
464 | #else | 465 | #else |
466 | /* | ||
467 | * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would | ||
468 | * schedule DABR | ||
469 | */ | ||
470 | #ifndef CONFIG_HAVE_HW_BREAKPOINT | ||
465 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | 471 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) |
466 | set_dabr(new->thread.dabr); | 472 | set_dabr(new->thread.dabr); |
473 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
467 | #endif | 474 | #endif |
468 | 475 | ||
469 | 476 | ||
470 | new_thread = &new->thread; | 477 | new_thread = &new->thread; |
471 | old_thread = ¤t->thread; | 478 | old_thread = ¤t->thread; |
472 | 479 | ||
480 | #if defined(CONFIG_PPC_BOOK3E_64) | ||
481 | /* XXX Current Book3E code doesn't deal with kernel side DBCR0, | ||
482 | * we always hold the user values, so we set it now. | ||
483 | * | ||
484 | * However, we ensure the kernel MSR:DE is appropriately cleared too | ||
485 | * to avoid spurrious single step exceptions in the kernel. | ||
486 | * | ||
487 | * This will have to change to merge with the ppc32 code at some point, | ||
488 | * but I don't like much what ppc32 is doing today so there's some | ||
489 | * thinking needed there | ||
490 | */ | ||
491 | if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) { | ||
492 | u32 dbcr0; | ||
493 | |||
494 | mtmsr(mfmsr() & ~MSR_DE); | ||
495 | isync(); | ||
496 | dbcr0 = mfspr(SPRN_DBCR0); | ||
497 | dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0; | ||
498 | mtspr(SPRN_DBCR0, dbcr0); | ||
499 | } | ||
500 | #endif /* CONFIG_PPC64_BOOK3E */ | ||
501 | |||
473 | #ifdef CONFIG_PPC64 | 502 | #ifdef CONFIG_PPC64 |
474 | /* | 503 | /* |
475 | * Collect processor utilization data per process | 504 | * Collect processor utilization data per process |
@@ -642,7 +671,11 @@ void flush_thread(void) | |||
642 | { | 671 | { |
643 | discard_lazy_cpu_state(); | 672 | discard_lazy_cpu_state(); |
644 | 673 | ||
674 | #ifdef CONFIG_HAVE_HW_BREAKPOINTS | ||
675 | flush_ptrace_hw_breakpoint(current); | ||
676 | #else /* CONFIG_HAVE_HW_BREAKPOINTS */ | ||
645 | set_debug_reg_defaults(¤t->thread); | 677 | set_debug_reg_defaults(¤t->thread); |
678 | #endif /* CONFIG_HAVE_HW_BREAKPOINTS */ | ||
646 | } | 679 | } |
647 | 680 | ||
648 | void | 681 | void |
@@ -660,6 +693,9 @@ void prepare_to_copy(struct task_struct *tsk) | |||
660 | flush_altivec_to_thread(current); | 693 | flush_altivec_to_thread(current); |
661 | flush_vsx_to_thread(current); | 694 | flush_vsx_to_thread(current); |
662 | flush_spe_to_thread(current); | 695 | flush_spe_to_thread(current); |
696 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
697 | flush_ptrace_hw_breakpoint(tsk); | ||
698 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
663 | } | 699 | } |
664 | 700 | ||
665 | /* | 701 | /* |