pk/Linux 上的 RISC-V ecall 系统调用调用约定

RISC-V ecall syscall calling convention on pk/Linux

在 RISC-V 伪内核 (pk) 或 Linux 下运行的程序中系统调用的调用约定是什么?

查看 riscv-gnu-toolchain 生成的代码,规则似乎是:

是这个吗?

真的有必要将未使用的参数清零吗?

寄存器a6呢?这可以用于另一个 sycall 参数吗?

调用 exit() 系统调用的示例:

li    a0, 1               # argument that is used by the syscall
li    a1, 0               # unused arguments
li    a2, 0
li    a3, 0
li    a4, 0
li    a5, 0
li    a7, 93              # exit syscall number

是的,基本上就是这样。

不,没有必要将未使用的参数清零。使用 riscv-gnu-toolchain(使用 newlib C 库)时将未使用的参数归零只是 newlib sycall 调用代码的产物。为了简单起见,代码只有一个 scall (old name for ecall) wrapper with 6 syscall arguments. Thus, the exit() implementation just calls that wrapper with some additional zeroes.

截至 2020 年,maximum number of syscall arguments in Linux is 6。伪内核也是如此。因此,a6 始终未使用。

Linux 和 pk 都在 a7 中提供系统调用编号。并且 pk 使用的系统调用编号遵循 Linux 标准。

syscall(2) Linux man-page also summarizes the calling conventions on different architectures, including RISC-V. It specifies a1 可能用于 return 第二个 return 值,但这与 glibc 和 newlib 中的代码不匹配。