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 GrantRegionAllocator
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
ProcessGrant
s 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.