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 <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2025-01-24 14:15:31 -08:00 committed by Benjamin Cabé
commit d725f37d5e

View file

@ -74,8 +74,38 @@ _not_checking_user_context:
movi a3, ~PS_OWB_MASK movi a3, ~PS_OWB_MASK
and a2, a2, a3 and a2, a2, a3
s32i a2, a0, ___xtensa_irq_bsa_t_ps_OFFSET 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. /* Need to setup PS so we can spill all registers.
* EXCM and RING bits need to be cleared as CPU * EXCM and RING bits need to be cleared as CPU
@ -98,29 +128,6 @@ _not_checking_user_context:
mov a1, a0 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 ODD_REG_SAVE a0, a1
call0 xtensa_save_high_regs call0 xtensa_save_high_regs