From d725f37d5ea2ac11fffa99dffea26a38b3e53b2c Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Fri, 24 Jan 2025 14:15:31 -0800 Subject: [PATCH] xtensa: userspace: calculate PC earlier at syscall entry This moves the calculation of the return PC earlier in syscall entry. There is no need to stash it into BSA, load it, do the calculation and save it back. We can do the calculation first and save it in BSA at the same time. Signed-off-by: Daniel Leung --- arch/xtensa/core/userspace.S | 57 ++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/arch/xtensa/core/userspace.S b/arch/xtensa/core/userspace.S index beba7c0e938..762a1fc25c1 100644 --- a/arch/xtensa/core/userspace.S +++ b/arch/xtensa/core/userspace.S @@ -74,8 +74,38 @@ _not_checking_user_context: movi a3, ~PS_OWB_MASK and a2, a2, a3 s32i a2, a0, ___xtensa_irq_bsa_t_ps_OFFSET - rsr.epc1 a2 - s32i a2, a0, ___xtensa_irq_bsa_t_pc_OFFSET + + /* Manipulate PC where we will return to after syscall. + * This is needed as syscall will stash the PC where + * the syscall instruction locates, instead of + * the instruction after it. + */ + rsr.epc1 a3 +#if XCHAL_HAVE_LOOPS + /* If the syscall instruction was the last instruction in the body of + * a zero-overhead loop, and the loop will execute again, decrement + * the loop count and resume execution at the head of the loop. + */ + rsr.lend a2 + addi a3, a3, 3 + bne a2, a3, end_loop + rsr.lcount a2 + beqz a2, end_loop + addi a2, a2, -1 + wsr.lcount a2 + rsr.lbeg a3 + + /* Make sure WSR above is synced before RSR in ODD_REG_SAVE. */ + isync +end_loop: +#else + /* EPC1 (and now a3) contains the address that invoked syscall. + * We need to increment it to execute the next instruction when + * we return. The instruction size is 3 bytes, so lets just add it. + */ + addi a3, a3, 3 +#endif + s32i a3, a0, ___xtensa_irq_bsa_t_pc_OFFSET /* Need to setup PS so we can spill all registers. * EXCM and RING bits need to be cleared as CPU @@ -98,29 +128,6 @@ _not_checking_user_context: mov a1, a0 - l32i a3, a1, ___xtensa_irq_bsa_t_pc_OFFSET -#if XCHAL_HAVE_LOOPS - /* If the syscall instruction was the last instruction in the body of - * a zero-overhead loop, and the loop will execute again, decrement - * the loop count and resume execution at the head of the loop. - */ - rsr.lend a2 - addi a3, a3, 3 - bne a2, a3, end_loop - rsr.lcount a2 - beqz a2, end_loop - addi a2, a2, -1 - wsr.lcount a2 - rsr.lbeg a3 -end_loop: -#else - /* EPC1 (and now a3) contains the address that invoked syscall. - * We need to increment it to execute the next instruction when - * we return. The instruction size is 3 bytes, so lets just add it. - */ - addi a3, a3, 3 -#endif - s32i a3, a1, ___xtensa_irq_bsa_t_pc_OFFSET ODD_REG_SAVE a0, a1 call0 xtensa_save_high_regs