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~

Reply via email to