Clarify some of the `memop` comments. It was not previously clear that some of the statements I made are true for the *current* memop operations and not necessarily true for future memop operations. I made the distinction more clear, plus added some comments so that future maintainers who add memop operations know to reevaluate the assumptions/statements I made.
diff --git a/core/platform/src/raw_syscalls.rs b/core/platform/src/raw_syscalls.rs index 5f95d2b..5a87b2d 100644 --- a/core/platform/src/raw_syscalls.rs +++ b/core/platform/src/raw_syscalls.rs
@@ -47,11 +47,16 @@ // Memop takes 1 or 2 arguments (operation and an optional argument). Because it // is part of the core kernel, it is okay for us to leave arbitrary data in the // argument register for operations where the argument register is unused -// (again, in line with Tock's threat model). Memop returns up to 2 return -// arguments, so we don't need to mark r2 and r3 as clobbered. As such, we need +// (again, in line with Tock's threat model). As such, for efficiency, we need // two raw memop calls: one for operations without an argument and one for // operations with an argument. // +// The success type for Memop calls depends on the operation perform. However, +// all *currently defined* memop operations return either Success or Success +// with u32. Therefore, the memop implementations only need to mark r0 and r1 as +// clobbered, not r2 and r3. This choice of clobbers will need to be revisited +// if and when a memop operation that returns more data is added. +// // Because the variables passed in and out of raw system calls represent // register values, they are of type usize. In cases where it doesn't make sense // to pass a pointer-sized value, libtock_unittest::FakeSyscalls may panic if a @@ -133,8 +138,8 @@ // // Design note: like raw_yield, this is safe because memops that currently // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize - // so that if the kernel adds an unsafe memop this API doesn't become - // unsound. + // so that if the kernel adds an unsafe memop -- or one that can clobber + // r2/r3 -- this API doesn't become unsound. fn zero_arg_memop(r0_in: ZeroArgMemop) -> (usize, usize); // one_arg_memop is used to invoke memop operations that take an argument. @@ -157,8 +162,8 @@ // // Design note: like raw_yield, this is safe because memops that currently // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize - // so that if the kernel adds an unsafe memop this API doesn't become - // unsound. + // so that if the kernel adds an unsafe memop -- or one that can clobber + // r2/r3 -- this API doesn't become unsound. fn one_arg_memop(r0_in: OneArgMemop, r1: usize) -> (usize, usize); } @@ -171,6 +176,8 @@ FlashRegionEnd = 9, SpecifyStackTop = 10, SpecifyHeapStart = 11, + // Note: before adding new memop operations, make sure the assumptions in + // the design notes on `one_arg_memop` are valid for the new operation type. } // TODO: When the numeric values (0 and 1) are assigned to the yield types, @@ -191,4 +198,7 @@ FlashEnd = 5, GrantStart = 6, FlashRegions = 7, + // Note: before adding new memop operations, make sure the assumptions in + // the design notes on `zero_arg_memop` are valid for the new operation + // type. }