On 12/14/21 12:01 AM, WANG Xuerui wrote:
+ move $t0, $a0 /* signal_pending pointer */
...
+safe_syscall_start:
+ /* If signal_pending is non-zero, don't do the call */
+ ld.w $t1, $t0, 0
+ bnez $t1, 2f
+ syscall 0
We need a non-syscall clobbered register for signal_pending, per the bug fixed in
5d9f3ea0817215ad4baac5aa30414e9ebbaaf0d6.
In the case of riscv, because of the way exceptions are delivered, there are no
syscall-clobbered registers (by the time syscall is distinguished from interrupt, all
registers have been saved).
In the case of mips, there are no non-syscall-clobbered registers that are not also
call-saved or syscall arguments, so I had to allocate a stack frame and save/restore s0.
For loongarch64, according to glibc,
#define __SYSCALL_CLOBBERS \
"$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
which does suggest that a6 is unused, saved across the syscall, and also call-clobbered
(so we don't have to allocate a stack frame).
I've had a browse through the loongarch kernel code and that seems to be all true.
(Curiously, loongarch restores more registers than it saves on the way out of
handle_syscall. There may be a subtle reason for that, or room for improvement.)
r~