doc/wg/core/notes/core-notes-2020-09-18.md
main.rs, because there's
still some issues with the underlying hardware.a very very very large number,
is that correct?a0 to a4. What this means is the syscall arguments
and return values are in a0 to a3, the C ABI calling convention
registers. When the syscall class ID was in a0, the first argument was in
a1. When you call a syscall, the kernel needs to shift the argument from
a1 to a0, and a2 to a1, etc, which takes code and time. It's not
clear necessarily that moves wouldn't need to happen with the suggested
design, but this way moves aren't forced to happen -- it is possible to write
a faster path. The question that came up is if we
jump down to section 4.2, the current approach is r0 is the driver ID and r1
is syscall ID, then parameters. This mostly matches the function signatures within
the kernel (allow is the exception). r0 is used to dispatch on driver ID and
replaced with the capsule's self, then r1, r2, r3, r4 can be passed
through unchanged. Vadim pointed out we don't have 2^32
commands or drivers, so why don't we compress them into a single register
(e.g. driver in the top 16 bits, the command ID is in the bottom 16 bits).
This would give us another register. E.g. in command, we could pass more
arguments. Downside is it's unclear which register it should be. If it is r0
it will be used by self within the kernel. Would somehow need to move
things around, and may make the kernel use the stack internally. I hope that
describes the tradeoff and I want to test the wind about peoples' thoughts.
Is it worth having potentially another argument into command and the
flexibility that gives worth it?command take 3 arguments, then
within the kernel, the capsules would take (self, command_id, arg1, arg2, arg3) which is 5 arguments, and runs the risk of spelling to the stack. The
Rust ABI is undefined, but my understanding is it doesn't have more
argument registers than the C ABI, and I don't think those calls will be
reliably inlined. Some of them are virtual calls.(self, minor, arg1, arg2, arg3).self is a pointer.get_commands in the Driver trait
which returns a slice.t0 in
RISC-V or r12 in ARM, then that register would be caller-saved anyway and
the fact you put the syscall number in it will not hurt.r0 through [unintelligible]libtock-rs independent of the current
implementation that is exposed publicly. I think it's probably time I
switched that rewrite to use the Tock 2.0 system calls. In part, because I
was following the Tock 1.x system call interface and due to the lack of
unallow I had to write some difficult code to handle allow buffers in a
memory-safe manner. I realize now I can't use those buffers from an
application -- the API is bad -- so I either need to go back and change those
significantly or I need to go to Tock 2.0 where I can pass native Rust types.
What I'm not sure is how stable people think it is -- little things like how
you pack things in registers don't matter here, but at the high level it
seems to be stabilizing. An additional benefit is I would be more likely to
catch memory safety issues posed by the syscall API design.libtock-rs.