Expand description

Support for processes granting memory from their allocations to the kernel.

Grant Overview

Grants allow capsules to dynamically allocate memory from a process to hold state on the process’s behalf.

Each capsule that wishes to do this needs to have a Grant type. Grants are created at boot, and each have a unique ID and a type T. This type only allows the capsule to allocate memory from a process in the future. It does not initially represent any allocated memory.

When a capsule does wish to use its Grant to allocate memory from a process, it must “enter” the Grant with a specific ProcessId. Entering a Grant for a specific process instructs the core kernel to create an object T in the process’s memory space and provide the capsule with access to it. If the Grant has not previously been entered for that process, the memory for object T will be allocated from the “grant region” within the kernel-accessible portion of the process’s memory.

If a Grant has never been entered for a process, the object T will not be allocated in that process’s grant region, even if the Grant has been entered for other processes.

Upcalls and allowed buffer references are stored in the dynamically allocated grant for a particular Driver as well. Upcalls and allowed buffer references are stored outside of the T object to enable the kernel to manage them and ensure swapping guarantees are met.

The type T of a Grant is fixed in size and the number of upcalls and allowed buffers associated with a grant is fixed. That is, when a Grant is entered for a process the resulting allocated object will be the size of SizeOf<T> plus the size for the structure to hold upcalls and allowed buffer references. If capsules need additional process-specific memory for their operation, they can use an Allocator to request additional memory from the process’s grant region.

                           ┌──────────────────┐
                           │                  │
                           │ Capsule          │
                           │                  │
                           └─┬────────────────┘
                             │ Capsules hold
                             │ references to
                             │ grants.
                             ▼
                           ┌──────────────────┐
                           │ Grant            │
                           │                  │
 Process Memory            │ Type: T          │
┌────────────────────────┐ │ grant_num: 1     │
│                        │ │ driver_num: 0x4  │
│  ...                   │ └───┬─────────────┬┘
├────────────────────────┤     │Each Grant   │
│ Grant       ptr 0      │     │has a pointer│
│ Pointers    ptr 1 ───┐ │ ◄───┘per process. │
│             ...      │ │                   │
│             ptr N    │ │                   │
├──────────────────────┼─┤                   │
│  ...                 │ │                   │
├──────────────────────┼─┤                   │
│ Grant Region         │ │     When a Grant  │
│                      │ │     is allocated  │
│ ┌─────────────────┐  │ │     for a process │
│ │ Allocated Grant │  │ │ ◄─────────────────┘
│ │                 │  │ │     it uses memory
│ │  [ SizeOf<T> ]  │  │ │     from the grant
│ │─────────────────│  │ │     region.
│ │ Padding         │  │ │
│ │─────────────────│  │ │
│ │ GrantKernelData │  │ │
│ └─────────────────┘◄─┘ │
│                        │
│ ┌─────────────────┐    │
│ │ Custom Grant    │    │ ◄── Capsules can
│ │                 │    │     allocate extra
│ └─────────────────┘    │     memory if needed.
│                        │
├─kernel_brk─────────────┤
│                        │
│ ...                    │
└────────────────────────┘

Grant Mechanisms and Types

Here is an overview of the types used by grant.rs to implement the Grant functionality in Tock:

                        ┌──────────────────────────┐
                        │ struct Grant<T, ...> {   │
                        │   driver_num: usize      │
                        │   grant_num: usize       │
                        │ }                        ├───┐
Entering a Grant for a  └──┬───────────────────────┘   │
process causes the         │                           │
memory for T to be         │ .enter(ProcessId)         │ .enter(ProcessId, fn)
allocated.                 ▼                           │
                        ┌──────────────────────────┐   │ For convenience,
ProcessGrant represents │ struct ProcessGrant<T> { │   │ allocating and getting
a Grant allocated for a │   number: usize          │   │ access to the T object
specific process.       │   process: &Process      │   │ is combined in one
                        │ }                        │   │ .enter() call.
A provided closure      └──┬───────────────────────┘   │
is given access to         │                           │
the underlying memory      │ .enter(fn)                │
where the T is stored.     ▼                           │
                        ┌────────────────────────────┐ │
GrantData wraps the     │ struct GrantData<T>   {    │◄┘
type and provides       │   data: &mut T             │
mutable access.         │ }                          │
GrantKernelData         │ struct GrantKernelData {   │
provides access to      │   upcalls: [SavedUpcall]   │
scheduling upcalls      │   allow_ro: [SavedAllowRo] │
and process buffers.    │   allow_rw: [SavedAllowRW] │
                        │ }                          │
                        └──┬─────────────────────────┘
The actual object T can    │
only be accessed inside    │ fn(mem: &GrantData, kernel_data: &GrantKernelData)
the closure.               ▼

Structs

Specifies how many read-only allows a grant instance supports automatically.

Specifies how many read-write allows a grant instance supports automatically.

Grant which was allocated from the kernel-owned grant region in a specific process’s memory, separately from a normal Grant.

Type for storing an object of type T in process memory that is only accessible by the kernel.

This GrantData object provides access to the memory allocated for a grant for a specific process.

This GrantKernelData object provides a handle to access upcalls and process buffers stored on behalf of a particular grant/driver.

Tool for allocating additional memory regions in a process’s grant region.

Type to iterate ProcessGrants across processes.

An instance of a grant allocated for a particular process.

Specifies how many upcalls a grant instance supports automatically.

Traits

Tracks how many read-only allows a grant instance supports automatically.

Tracks how many read-write allows a grant instance supports automatically.

Tracks how many upcalls a grant instance supports automatically.