diff options
author | Christophe Leroy <christophe.leroy@csgroup.eu> | 2021-02-09 19:29:28 +0000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2021-02-11 23:35:12 +1100 |
commit | d524dda719f06967db4d3ba519edf9267f84c155 (patch) | |
tree | 91120a551f132ba10a5a711b2a01bc452d7380af /arch/powerpc/kernel/interrupt.c | |
parent | b966f2279048ee9f30d83ef8568b99fa40917c54 (diff) | |
download | linux-d524dda719f06967db4d3ba519edf9267f84c155.tar.gz linux-d524dda719f06967db4d3ba519edf9267f84c155.tar.bz2 linux-d524dda719f06967db4d3ba519edf9267f84c155.zip |
powerpc/32: Handle bookE debugging in C in syscall entry/exit
The handling of SPRN_DBCR0 and other registers can easily
be done in C instead of ASM.
For that, create booke_load_dbcr0() and booke_restore_dbcr0().
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/1a7515f9258b27a9177de88491a8bb79b255ceb7.1612898425.git.christophe.leroy@csgroup.eu
Diffstat (limited to 'arch/powerpc/kernel/interrupt.c')
-rw-r--r-- | arch/powerpc/kernel/interrupt.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c index 75d657b63332..f93664ad4a5e 100644 --- a/arch/powerpc/kernel/interrupt.c +++ b/arch/powerpc/kernel/interrupt.c @@ -73,6 +73,8 @@ notrace long system_call_exception(long r3, long r4, long r5, kuap_check_amr(); #endif + booke_restore_dbcr0(); + account_cpu_user_entry(); account_stolen_time(); @@ -204,6 +206,28 @@ static notrace inline bool prep_irq_for_enabled_exit(bool clear_ri, bool irqs_en return false; } +static notrace void booke_load_dbcr0(void) +{ +#ifdef CONFIG_PPC_ADV_DEBUG_REGS + unsigned long dbcr0 = current->thread.debug.dbcr0; + + if (likely(!(dbcr0 & DBCR0_IDM))) + return; + + /* + * Check to see if the dbcr0 register is set up to debug. + * Use the internal debug mode bit to do this. + */ + mtmsr(mfmsr() & ~MSR_DE); + if (IS_ENABLED(CONFIG_PPC32)) { + isync(); + global_dbcr0[smp_processor_id()] = mfspr(SPRN_DBCR0); + } + mtspr(SPRN_DBCR0, dbcr0); + mtspr(SPRN_DBSR, -1); +#endif +} + /* * This should be called after a syscall returns, with r3 the return value * from the syscall. If this function returns non-zero, the system call @@ -317,6 +341,8 @@ again: local_paca->tm_scratch = regs->msr; #endif + booke_load_dbcr0(); + account_cpu_user_exit(); #ifdef CONFIG_PPC_BOOK3S_64 /* BOOK3E and ppc32 not using this */ @@ -331,9 +357,6 @@ again: #ifndef CONFIG_PPC_BOOK3E_64 /* BOOK3E not yet using this */ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned long msr) { -#ifdef CONFIG_PPC_BOOK3E - struct thread_struct *ts = ¤t->thread; -#endif unsigned long *ti_flagsp = ¤t_thread_info()->flags; unsigned long ti_flags; unsigned long flags; @@ -398,17 +421,7 @@ again: goto again; } -#ifdef CONFIG_PPC_BOOK3E - if (unlikely(ts->debug.dbcr0 & DBCR0_IDM)) { - /* - * Check to see if the dbcr0 register is set up to debug. - * Use the internal debug mode bit to do this. - */ - mtmsr(mfmsr() & ~MSR_DE); - mtspr(SPRN_DBCR0, ts->debug.dbcr0); - mtspr(SPRN_DBSR, -1); - } -#endif + booke_load_dbcr0(); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM local_paca->tm_scratch = regs->msr; |