The handling of SPRN_DBCR0 and other registers can easily be done in C instead of ASM.
Signed-off-by: Christophe Leroy <christophe.le...@csgroup.eu> --- v5: New --- arch/powerpc/include/asm/reg_booke.h | 3 +++ arch/powerpc/kernel/entry_32.S | 7 ------- arch/powerpc/kernel/head_32.h | 15 -------------- arch/powerpc/kernel/head_booke.h | 19 ------------------ arch/powerpc/kernel/interrupt.c | 29 +++++++++++++++++++++++++++- 5 files changed, 31 insertions(+), 42 deletions(-) diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 262782f08fd4..17b8dcd9a40d 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h @@ -691,6 +691,9 @@ #define mttmr(rn, v) asm volatile(MTTMR(rn, %0) : \ : "r" ((unsigned long)(v)) \ : "memory") + +extern unsigned long global_dbcr0[]; + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_POWERPC_REG_BOOKE_H__ */ diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index a574201b0eb6..8dea4d3b1d06 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -342,13 +342,6 @@ transfer_to_syscall: ret_from_syscall: addi r4,r1,STACK_FRAME_OVERHEAD bl syscall_exit_prepare -#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) - /* If the process has its own DBCR0 value, load it up. The internal - debug mode bit tells us that dbcr0 should be loaded. */ - lwz r0,THREAD+THREAD_DBCR0(r2) - andis. r10,r0,DBCR0_IDM@h - bnel- load_dbcr0 -#endif #ifdef CONFIG_PPC_47x lis r4,icache_44x_need_flush@ha lwz r5,icache_44x_need_flush@l(r4) diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h index 5001c6ecc3ec..961b1ce3b6bf 100644 --- a/arch/powerpc/kernel/head_32.h +++ b/arch/powerpc/kernel/head_32.h @@ -153,21 +153,6 @@ SAVE_4GPRS(3, r11) SAVE_2GPRS(7, r11) addi r2,r12,-THREAD -#if defined(CONFIG_40x) - /* Check to see if the dbcr0 register is set up to debug. Use the - internal debug mode bit to do this. */ - lwz r12,THREAD_DBCR0(r12) - andis. r12,r12,DBCR0_IDM@h - beq+ 3f - /* From user and task is ptraced - load up global dbcr0 */ - li r12,-1 /* clear all pending debug events */ - mtspr SPRN_DBSR,r12 - lis r11,global_dbcr0@ha - addi r11,r11,global_dbcr0@l - lwz r12,0(r11) - mtspr SPRN_DBCR0,r12 -3: -#endif b transfer_to_syscall /* jump to handler */ .endm diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index 5f565232b99d..47857795f50a 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h @@ -130,25 +130,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV) SAVE_2GPRS(7, r11) addi r2,r10,-THREAD - /* Check to see if the dbcr0 register is set up to debug. Use the - internal debug mode bit to do this. */ - lwz r12,THREAD_DBCR0(r10) - andis. r12,r12,DBCR0_IDM@h - beq+ 3f - /* From user and task is ptraced - load up global dbcr0 */ - li r12,-1 /* clear all pending debug events */ - mtspr SPRN_DBSR,r12 - lis r11,global_dbcr0@ha - addi r11,r11,global_dbcr0@l -#ifdef CONFIG_SMP - lwz r10, TASK_CPU(r2) - slwi r10, r10, 2 - add r11, r11, r10 -#endif - lwz r12,0(r11) - mtspr SPRN_DBCR0,r12 - -3: b transfer_to_syscall /* jump to handler */ .endm diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c index c89a8eac3e24..6111acf61373 100644 --- a/arch/powerpc/kernel/interrupt.c +++ b/arch/powerpc/kernel/interrupt.c @@ -76,6 +76,13 @@ notrace long system_call_exception(long r3, long r4, long r5, kuap_check_amr(); #endif +#ifdef CONFIG_PPC_ADV_DEBUG_REGS + if (IS_ENABLED(CONFIG_PPC32) && unlikely(current->thread.debug.dbcr0 & DBCR0_IDM)) { + mtspr(SPRN_DBSR, -1); + mtspr(SPRN_DBCR0, global_dbcr0[smp_processor_id()]); + } +#endif + account_cpu_user_entry(); account_stolen_time(); @@ -324,6 +331,22 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3, local_paca->tm_scratch = regs->msr; #endif +#ifdef CONFIG_PPC_ADV_DEBUG_REGS + if (unlikely(current->thread.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); + if (IS_ENABLED(CONFIG_PPC32)) { + isync(); + global_dbcr0[smp_processor_id()] = mfspr(SPRN_DBCR0); + } + mtspr(SPRN_DBCR0, current->thread.debug.dbcr0); + mtspr(SPRN_DBSR, -1); + } +#endif + account_cpu_user_exit(); #ifdef CONFIG_PPC_BOOK3S_64 /* BOOK3E and ppc32 not using this */ @@ -401,13 +424,17 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned goto again; } -#ifdef CONFIG_PPC_BOOK3E +#ifdef CONFIG_PPC_ADV_DEBUG_REGS if (unlikely(current->thread.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); + if (IS_ENABLED(CONFIG_PPC32)) { + isync(); + global_dbcr0[smp_processor_id()] = mfspr(SPRN_DBCR0); + } mtspr(SPRN_DBCR0, current->thread.debug.dbcr0); mtspr(SPRN_DBSR, -1); } -- 2.25.0