maxschlepzig
maxschlepzig

Reputation: 39135

RISC-V ecall syscall calling convention on pk/Linux

What is the calling convention for a syscall in a program that runs under the RISC-V pseudo-kernel (pk) or Linux?

Looking at the code generated by the riscv-gnu-toolchain the rules seem to be:

Is this it?

Is it really necessary to zero-out the unused arguments?

What about register a6? Can this be used for yet another sycall argument?

Example that calls the exit() syscall:

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

Upvotes: 10

Views: 10624

Answers (1)

maxschlepzig
maxschlepzig

Reputation: 39135

Yes, this is basically it.

No, it isn't necessary to zero out the unused arguments. The zeroing out of unused arguments when using the riscv-gnu-toolchain (with the newlib C library) is just an artifact of the newlib sycall calling code. To keep it simple, the code has a single scall (old name for ecall) wrapper with 6 syscall arguments. Thus, the exit() implementation just calls that wrapper with some additional zeroes.

As of 2020, the maximum number of syscall arguments in Linux is 6. The same goes for the pseudo-kernel. Thus, a6 is always unused.

Both Linux and pk supply the syscall number in a7. And the syscall numbers used by pk follow the Linux standard.

The syscall(2) Linux man-page also summarizes the calling conventions on different architectures, including RISC-V. It specifies a1 as possibly used to return a second return value, but this doesn't match the code in glibc and newlib.

Upvotes: 8

Related Questions