Module kernel::syscall

source ·
Expand description

Mechanisms for handling and defining system calls.

§System Call Overview

Tock supports six system calls. The allow_readonly, allow_readwrite, subscribe, yield, and memop system calls are handled by the core kernel, while command is implemented by drivers. The main system calls:

  • subscribe passes a upcall to the driver which it can invoke on the process later, when an event has occurred or data of interest is available.
  • command tells the driver to do something immediately.
  • allow_readwrite provides the driver read-write access to an application buffer.
  • allow_userspace_readable provides the driver read-write access to an application buffer that is still shared with the app.
  • allow_readonly provides the driver read-only access to an application buffer.

§Mapping system-calls to drivers

Each of these three system calls takes at least two parameters. The first is a driver identifier and tells the scheduler which driver to forward the system call to. The second parameters is a _syscall number and is used by the driver to differentiate instances of the call with different driver-specific meanings (e.g. subscribe for “data received” vs subscribe for “send completed”). The mapping between driver identifiers and drivers is determined by a particular platform, while the syscall number is driver-specific.

One convention in Tock is that driver minor number 0 for the command syscall can always be used to determine if the driver is supported by the running kernel by checking the return code. If the return value is greater than or equal to zero then the driver is present. Typically this is implemented by a null command that only returns 0, but in some cases the command can also return more information, like the number of supported devices (useful for things like the number of LEDs).

§The yield system call class

While drivers do not handle yield system calls, it is important to understand them and how they interact with subscribe, which registers upcall functions with the kernel. When a process calls a yield system call, the kernel checks if there are any pending upcalls for the process. If there are pending upcalls, it pushes one upcall onto the process stack. If there are no pending upcalls, yield-wait will cause the process to sleep until a upcall is triggered, while yield-no-wait returns immediately.

§Method result types

Each driver method has a limited set of valid return types. Every method has a single return type corresponding to success and a single return type corresponding to failure. For the subscribe and allow system calls, these return types are the same for every instance of those calls. Each instance of the command system call, however, has its own specified return types. A command that requests a timestamp, for example, might return a 32-bit number on success and an error code on failure, while a command that requests time of day in microsecond granularity might return a 64-bit number and a 32-bit timezone encoding on success, and an error code on failure.

These result types are represented as safe Rust types. The core kernel (the scheduler and syscall dispatcher) is responsible for encoding these types into the Tock system call ABI specification.

Structs§

  • Possible return values of a command driver method, as specified in TRD104.

Enums§

  • ContextSwitchReason specifies why the process stopped executing and execution returned to the kernel.
  • Decoded system calls as defined in TRD104.
  • Enumeration of the system call classes based on the identifiers specified in the Tock ABI.
  • Enumeration of the possible system call return variants.
  • Enumeration of the yield system calls based on the Yield identifier values specified in the Tock ABI.

Traits§

  • Trait for capsules implementing peripheral driver system calls specified in TRD104. The kernel translates the values passed from userspace into Rust types and includes which process is making the call. All of these system calls perform very little synchronous work; long running computations or I/O should be split-phase, with an upcall indicating their completion.
  • The UserspaceKernelBoundary trait is implemented by the architectural component of the chip implementation of Tock. This trait allows the kernel to switch to and from processes in an architecture-independent manner.