kernel/
grant.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Support for processes granting memory from their allocations to the kernel.
6//!
7//! ## Grant Overview
8//!
9//! Grants allow capsules to dynamically allocate memory from a process to hold
10//! state on the process's behalf.
11//!
12//! Each capsule that wishes to do this needs to have a [`Grant`] type. Grants
13//! are created at boot, and each have a unique ID and a type `T`. This type
14//! only allows the capsule to allocate memory from a process in the future. It
15//! does not initially represent any allocated memory.
16//!
17//! When a capsule does wish to use its Grant to allocate memory from a process,
18//! it must "enter" the Grant with a specific [`ProcessId`]. Entering a Grant
19//! for a specific process instructs the core kernel to create an object `T` in
20//! the process's memory space and provide the capsule with access to it. If the
21//! Grant has not previously been entered for that process, the memory for
22//! object `T` will be allocated from the "grant region" within the
23//! kernel-accessible portion of the process's memory.
24//!
25//! If a Grant has never been entered for a process, the object `T` will _not_
26//! be allocated in that process's grant region, even if the `Grant` has been
27//! entered for other processes.
28//!
29//! Upcalls and allowed buffer references are stored in the dynamically
30//! allocated grant for a particular Driver as well. Upcalls and allowed buffer
31//! references are stored outside of the `T` object to enable the kernel to
32//! manage them and ensure swapping guarantees are met.
33//!
34//! The type `T` of a Grant is fixed in size and the number of upcalls and
35//! allowed buffers associated with a grant is fixed. That is, when a Grant is
36//! entered for a process the resulting allocated object will be the size of
37//! `SizeOf<T>` plus the size for the structure to hold upcalls and allowed
38//! buffer references. If capsules need additional process-specific memory for
39//! their operation, they can use an [`GrantRegionAllocator`] to request
40//! additional memory from the process's grant region.
41//!
42//! ```text,ignore
43//!                            ┌──────────────────┐
44//!                            │                  │
45//!                            │ Capsule          │
46//!                            │                  │
47//!                            └─┬────────────────┘
48//!                              │ Capsules hold
49//!                              │ references to
50//!                              │ grants.
51//!                              ▼
52//!                            ┌──────────────────┐
53//!                            │ Grant            │
54//!                            │                  │
55//!  Process Memory            │ Type: T          │
56//! ┌────────────────────────┐ │ grant_num: 1     │
57//! │                        │ │ driver_num: 0x4  │
58//! │  ...                   │ └───┬─────────────┬┘
59//! ├────────────────────────┤     │Each Grant   │
60//! │ Grant       ptr 0      │     │has a pointer│
61//! │ Pointers    ptr 1 ───┐ │ ◄───┘per process. │
62//! │             ...      │ │                   │
63//! │             ptr N    │ │                   │
64//! ├──────────────────────┼─┤                   │
65//! │  ...                 │ │                   │
66//! ├──────────────────────┼─┤                   │
67//! │ Grant Region         │ │     When a Grant  │
68//! │                      │ │     is allocated  │
69//! │ ┌─────────────────┐  │ │     for a process │
70//! │ │ Allocated Grant │  │ │ ◄─────────────────┘
71//! │ │                 │  │ │     it uses memory
72//! │ │  [ SizeOf<T> ]  │  │ │     from the grant
73//! │ │─────────────────│  │ │     region.
74//! │ │ Padding         │  │ │
75//! │ │─────────────────│  │ │
76//! │ │ GrantKernelData │  │ │
77//! │ └─────────────────┘◄─┘ │
78//! │                        │
79//! │ ┌─────────────────┐    │
80//! │ │ Custom Grant    │    │ ◄── Capsules can
81//! │ │                 │    │     allocate extra
82//! │ └─────────────────┘    │     memory if needed.
83//! │                        │
84//! ├─kernel_brk─────────────┤
85//! │                        │
86//! │ ...                    │
87//! └────────────────────────┘
88//! ```
89//!
90//! ## Grant Mechanisms and Types
91//!
92//! Here is an overview of the types used by grant.rs to implement the Grant
93//! functionality in Tock:
94//!
95//! ```text,ignore
96//!                         ┌──────────────────────────┐
97//!                         │ struct Grant<T, ...> {   │
98//!                         │   driver_num: usize      │
99//!                         │   grant_num: usize       │
100//!                         │ }                        ├───┐
101//! Entering a Grant for a  └──┬───────────────────────┘   │
102//! process causes the         │                           │
103//! memory for T to be         │ .enter(ProcessId)         │ .enter(ProcessId, fn)
104//! allocated.                 ▼                           │
105//!                         ┌──────────────────────────┐   │ For convenience,
106//! ProcessGrant represents │ struct ProcessGrant<T> { │   │ allocating and getting
107//! a Grant allocated for a │   number: usize          │   │ access to the T object
108//! specific process.       │   process: &Process      │   │ is combined in one
109//!                         │ }                        │   │ .enter() call.
110//! A provided closure      └──┬───────────────────────┘   │
111//! is given access to         │                           │
112//! the underlying memory      │ .enter(fn)                │
113//! where the T is stored.     ▼                           │
114//!                         ┌────────────────────────────┐ │
115//! GrantData wraps the     │ struct GrantData<T>   {    │◄┘
116//! type and provides       │   data: &mut T             │
117//! mutable access.         │ }                          │
118//! GrantKernelData         │ struct GrantKernelData {   │
119//! provides access to      │   upcalls: [SavedUpcall]   │
120//! scheduling upcalls      │   allow_ro: [SavedAllowRo] │
121//! and process buffers.    │   allow_rw: [SavedAllowRW] │
122//!                         │ }                          │
123//!                         └──┬─────────────────────────┘
124//! The actual object T can    │
125//! only be accessed inside    │ fn(mem: &GrantData, kernel_data: &GrantKernelData)
126//! the closure.               ▼
127//! ```
128
129use core::cmp;
130use core::marker::PhantomData;
131use core::mem::{align_of, size_of};
132use core::ops::{Deref, DerefMut};
133use core::ptr::{write, NonNull};
134use core::slice;
135
136use crate::kernel::Kernel;
137use crate::process::{Error, Process, ProcessCustomGrantIdentifier, ProcessId};
138use crate::processbuffer::{ReadOnlyProcessBuffer, ReadWriteProcessBuffer};
139use crate::processbuffer::{ReadOnlyProcessBufferRef, ReadWriteProcessBufferRef};
140use crate::upcall::{Upcall, UpcallError, UpcallId};
141use crate::utilities::capability_ptr::CapabilityPtr;
142use crate::utilities::machine_register::MachineRegister;
143use crate::ErrorCode;
144
145/// Tracks how many upcalls a grant instance supports automatically.
146pub trait UpcallSize {
147    /// The number of upcalls the grant supports.
148    const COUNT: u8;
149}
150
151/// Specifies how many upcalls a grant instance supports automatically.
152pub struct UpcallCount<const NUM: u8>;
153impl<const NUM: u8> UpcallSize for UpcallCount<NUM> {
154    const COUNT: u8 = NUM;
155}
156
157/// Tracks how many read-only allows a grant instance supports automatically.
158pub trait AllowRoSize {
159    /// The number of read-only allows the grant supports.
160    const COUNT: u8;
161}
162
163/// Specifies how many read-only allows a grant instance supports automatically.
164pub struct AllowRoCount<const NUM: u8>;
165impl<const NUM: u8> AllowRoSize for AllowRoCount<NUM> {
166    const COUNT: u8 = NUM;
167}
168
169/// Tracks how many read-write allows a grant instance supports automatically.
170pub trait AllowRwSize {
171    /// The number of read-write allows the grant supports.
172    const COUNT: u8;
173}
174
175/// Specifies how many read-write allows a grant instance supports
176/// automatically.
177pub struct AllowRwCount<const NUM: u8>;
178impl<const NUM: u8> AllowRwSize for AllowRwCount<NUM> {
179    const COUNT: u8 = NUM;
180}
181
182/// Helper that calculated offsets within the kernel owned memory (i.e. the
183/// non-T part of grant).
184///
185/// Example layout of full grant belonging to a single app and driver:
186///
187/// ```text,ignore
188/// 0x003FFC8  ┌────────────────────────────────────┐
189///            │   T                                |
190/// 0x003FFxx  ├  ───────────────────────── ┐ K     |
191///            │   Padding (ensure T aligns)| e     |
192/// 0x003FF44  ├  ───────────────────────── | r     |
193///            │   SavedAllowRwN            | n     |
194///            │   ...                      | e     | G
195///            │   SavedAllowRw1            | l     | r
196///            │   SavedAllowRw0            |       | a
197/// 0x003FF44  ├  ───────────────────────── | O     | n
198///            │   SavedAllowRoN            | w     | t
199///            │   ...                      | n     |
200///            │   SavedAllowRo1            | e     | M
201///            │   SavedAllowRo0            | d     | e
202/// 0x003FF30  ├  ───────────────────────── |       | m
203///            │   SavedUpcallN             | D     | o
204///            │   ...                      | a     | r
205///            │   SavedUpcall1             | t     | y
206///            │   SavedUpcall0             | a     |
207/// 0x003FF24  ├  ───────────────────────── |       |
208///            │   Counters (usize)         |       |
209/// 0x003FF20  └────────────────────────────────────┘
210/// ```
211///
212/// The counters structure is composed as:
213///
214/// ```text,ignore
215/// 0             1             2             3         bytes
216/// |-------------|-------------|-------------|-------------|
217/// | # Upcalls   | # RO Allows | # RW Allows | [unused]    |
218/// |-------------|-------------|-------------|-------------|
219/// ```
220///
221/// This type is created whenever a grant is entered, and is responsible for
222/// ensuring that the grant is closed when it is no longer used. On `Drop`, we
223/// leave the grant. This protects against calling `grant.enter()` without
224/// calling the corresponding `grant.leave()`, perhaps due to accidentally using
225/// the `?` operator.
226struct EnteredGrantKernelManagedLayout<'a> {
227    /// Leaving a grant is handled through the process implementation, so must
228    /// keep a reference to the relevant process.
229    process: &'a dyn Process,
230    /// The grant number of the entered grant that we want to ensure we leave
231    /// properly.
232    grant_num: usize,
233
234    /// The location of the counters structure for the grant.
235    counters_ptr: *mut usize,
236    /// Pointer to the array of saved upcalls.
237    upcalls_array: *mut SavedUpcall,
238    /// Pointer to the array of saved read-only allows.
239    allow_ro_array: *mut SavedAllowRo,
240    /// Pointer to the array of saved read-write allows.
241    allow_rw_array: *mut SavedAllowRw,
242}
243
244/// Represents the number of the upcall elements in the kernel owned section of
245/// the grant.
246#[derive(Copy, Clone)]
247struct UpcallItems(u8);
248/// Represents the number of the read-only allow elements in the kernel owned
249/// section of the grant.
250#[derive(Copy, Clone)]
251struct AllowRoItems(u8);
252/// Represents the number of the read-write allow elements in the kernel owned
253/// section of the grant.
254#[derive(Copy, Clone)]
255struct AllowRwItems(u8);
256/// Represents the size data (in bytes) T within the grant.
257#[derive(Copy, Clone)]
258struct GrantDataSize(usize);
259/// Represents the alignment of data T within the grant.
260#[derive(Copy, Clone)]
261struct GrantDataAlign(usize);
262
263impl<'a> EnteredGrantKernelManagedLayout<'a> {
264    /// Reads the specified pointer as the base of the kernel owned grant region
265    /// that has previously been initialized.
266    ///
267    /// # Safety
268    ///
269    /// The incoming base pointer must be well aligned and already contain
270    /// initialized data in the expected form. There must not be any other
271    /// `EnteredGrantKernelManagedLayout` for the given `base_ptr` at the same
272    /// time, otherwise multiple mutable references to the same upcall/allow
273    /// slices could be created.
274    unsafe fn read_from_base(
275        base_ptr: NonNull<u8>,
276        process: &'a dyn Process,
277        grant_num: usize,
278    ) -> Self {
279        let counters_ptr = base_ptr.as_ptr() as *mut usize;
280        let counters_val = counters_ptr.read();
281
282        // Parse the counters field for each of the fields
283        let [_, _, allow_ro_num, upcalls_num] = u32::to_be_bytes(counters_val as u32);
284
285        // Skip over the counter usize, then the stored array of `SavedAllowRo`
286        // items and `SavedAllowRw` items.
287        let upcalls_array = counters_ptr.add(1) as *mut SavedUpcall;
288        let allow_ro_array = upcalls_array.add(upcalls_num as usize) as *mut SavedAllowRo;
289        let allow_rw_array = allow_ro_array.add(allow_ro_num as usize) as *mut SavedAllowRw;
290
291        Self {
292            process,
293            grant_num,
294            counters_ptr,
295            upcalls_array,
296            allow_ro_array,
297            allow_rw_array,
298        }
299    }
300
301    /// Creates a layout from the specified pointer and lengths of arrays and
302    /// initializes the kernel owned portion of the layout.
303    ///
304    /// # Safety
305    ///
306    /// The incoming base pointer must be well aligned and reference enough
307    /// memory to hold the entire kernel managed grant structure. There must
308    /// not be any other `EnteredGrantKernelManagedLayout` for
309    /// the given `base_ptr` at the same time, otherwise multiple mutable
310    /// references to the same upcall/allow slices could be created.
311    unsafe fn initialize_from_counts(
312        base_ptr: NonNull<u8>,
313        upcalls_num_val: UpcallItems,
314        allow_ro_num_val: AllowRoItems,
315        allow_rw_num_val: AllowRwItems,
316        process: &'a dyn Process,
317        grant_num: usize,
318    ) -> Self {
319        let counters_ptr = base_ptr.as_ptr() as *mut usize;
320
321        // Create the counters usize value by correctly packing the various
322        // counts into 8 bit fields.
323        let counter: usize =
324            u32::from_be_bytes([0, allow_rw_num_val.0, allow_ro_num_val.0, upcalls_num_val.0])
325                as usize;
326
327        let upcalls_array = counters_ptr.add(1) as *mut SavedUpcall;
328        let allow_ro_array = upcalls_array.add(upcalls_num_val.0.into()) as *mut SavedAllowRo;
329        let allow_rw_array = allow_ro_array.add(allow_ro_num_val.0.into()) as *mut SavedAllowRw;
330
331        counters_ptr.write(counter);
332        write_default_array(upcalls_array, upcalls_num_val.0.into());
333        write_default_array(allow_ro_array, allow_ro_num_val.0.into());
334        write_default_array(allow_rw_array, allow_rw_num_val.0.into());
335
336        Self {
337            process,
338            grant_num,
339            counters_ptr,
340            upcalls_array,
341            allow_ro_array,
342            allow_rw_array,
343        }
344    }
345
346    /// Returns the entire grant size including the kernel owned memory,
347    /// padding, and data for T. Requires that grant_t_align be a power of 2,
348    /// which is guaranteed from align_of rust calls.
349    fn grant_size(
350        upcalls_num: UpcallItems,
351        allow_ro_num: AllowRoItems,
352        allow_rw_num: AllowRwItems,
353        grant_t_size: GrantDataSize,
354        grant_t_align: GrantDataAlign,
355    ) -> usize {
356        let kernel_managed_size = size_of::<usize>()
357            + upcalls_num.0 as usize * size_of::<SavedUpcall>()
358            + allow_ro_num.0 as usize * size_of::<SavedAllowRo>()
359            + allow_rw_num.0 as usize * size_of::<SavedAllowRw>();
360        // We know that grant_t_align is a power of 2, so we can make a mask
361        // that will save only the remainder bits.
362        let grant_t_align_mask = grant_t_align.0 - 1;
363        // Determine padding to get to the next multiple of grant_t_align by
364        // taking the remainder and subtracting that from the alignment, then
365        // ensuring a full alignment value maps to 0.
366        let padding =
367            (grant_t_align.0 - (kernel_managed_size & grant_t_align_mask)) & grant_t_align_mask;
368        kernel_managed_size + padding + grant_t_size.0
369    }
370
371    /// Returns the alignment of the entire grant region based on the alignment
372    /// of data T.
373    fn grant_align(grant_t_align: GrantDataAlign) -> usize {
374        // The kernel owned memory all aligned to usize. We need to use the
375        // higher of the two alignment to ensure our padding calculations work
376        // for any alignment of T.
377        cmp::max(align_of::<usize>(), grant_t_align.0)
378    }
379
380    /// Returns the offset for the grant data t within the entire grant region.
381    ///
382    /// # Safety
383    ///
384    /// The caller must ensure that the specified base pointer is aligned to at
385    /// least the alignment of T and points to a grant that is of size
386    /// grant_size bytes.
387    unsafe fn offset_of_grant_data_t(
388        base_ptr: NonNull<u8>,
389        grant_size: usize,
390        grant_t_size: GrantDataSize,
391    ) -> NonNull<u8> {
392        // The location of the grant data T is the last element in the entire
393        // grant region. Caller must verify that memory is accessible and well
394        // aligned to T.
395        let grant_t_size_usize: usize = grant_t_size.0;
396        NonNull::new_unchecked(base_ptr.as_ptr().add(grant_size - grant_t_size_usize))
397    }
398
399    /// Read an 8 bit value from the counter field offset by the specified
400    /// number of bits. This is a helper function for reading the counter field.
401    fn get_counter_offset(&self, offset_bits: usize) -> usize {
402        // # Safety
403        //
404        // Creating a `EnteredGrantKernelManagedLayout` object requires that the
405        // pointers are well aligned and point to valid memory.
406        let counters_val = unsafe { self.counters_ptr.read() };
407        (counters_val >> offset_bits) & 0xFF
408    }
409
410    /// Return the number of upcalls stored by the core kernel for this grant.
411    fn get_upcalls_number(&self) -> usize {
412        self.get_counter_offset(0)
413    }
414
415    /// Return the number of read-only allow buffers stored by the core kernel
416    /// for this grant.
417    fn get_allow_ro_number(&self) -> usize {
418        self.get_counter_offset(8)
419    }
420
421    /// Return the number of read-write allow buffers stored by the core kernel
422    /// for this grant.
423    fn get_allow_rw_number(&self) -> usize {
424        self.get_counter_offset(16)
425    }
426
427    /// Return mutable access to the slice of stored upcalls for this grant.
428    /// This is necessary for storing a new upcall.
429    fn get_upcalls_slice(&mut self) -> &mut [SavedUpcall] {
430        // # Safety
431        //
432        // Creating a `EnteredGrantKernelManagedLayout` object ensures that the
433        // pointer to the upcall array is valid.
434        unsafe { slice::from_raw_parts_mut(self.upcalls_array, self.get_upcalls_number()) }
435    }
436
437    /// Return mutable access to the slice of stored read-only allow buffers for
438    /// this grant. This is necessary for storing a new read-only allow.
439    fn get_allow_ro_slice(&mut self) -> &mut [SavedAllowRo] {
440        // # Safety
441        //
442        // Creating a `EnteredGrantKernelManagedLayout` object ensures that the
443        // pointer to the RO allow array is valid.
444        unsafe { slice::from_raw_parts_mut(self.allow_ro_array, self.get_allow_ro_number()) }
445    }
446
447    /// Return mutable access to the slice of stored read-write allow buffers
448    /// for this grant. This is necessary for storing a new read-write allow.
449    fn get_allow_rw_slice(&mut self) -> &mut [SavedAllowRw] {
450        // # Safety
451        //
452        // Creating a `EnteredGrantKernelManagedLayout` object ensures that the
453        // pointer to the RW allow array is valid.
454        unsafe { slice::from_raw_parts_mut(self.allow_rw_array, self.get_allow_rw_number()) }
455    }
456
457    /// Return slices to the kernel managed upcalls and allow buffers. This
458    /// permits using upcalls and allow buffers when a capsule is accessing a
459    /// grant.
460    fn get_resource_slices(&self) -> (&[SavedUpcall], &[SavedAllowRo], &[SavedAllowRw]) {
461        // # Safety
462        //
463        // Creating a `EnteredGrantKernelManagedLayout` object ensures that the
464        // pointer to the upcall array is valid.
465        let upcall_slice =
466            unsafe { slice::from_raw_parts(self.upcalls_array, self.get_upcalls_number()) };
467
468        // # Safety
469        //
470        // Creating a `EnteredGrantKernelManagedLayout` object ensures that the
471        // pointer to the RO allow array is valid.
472        let allow_ro_slice =
473            unsafe { slice::from_raw_parts(self.allow_ro_array, self.get_allow_ro_number()) };
474
475        // # Safety
476        //
477        // Creating a `KernelManagedLayout` object ensures that the pointer to
478        // the RW allow array is valid.
479        let allow_rw_slice =
480            unsafe { slice::from_raw_parts(self.allow_rw_array, self.get_allow_rw_number()) };
481
482        (upcall_slice, allow_ro_slice, allow_rw_slice)
483    }
484}
485
486// Ensure that we leave the grant once this goes out of scope.
487impl Drop for EnteredGrantKernelManagedLayout<'_> {
488    fn drop(&mut self) {
489        // ### Safety
490        //
491        // To safely call this function we must ensure that no references will
492        // exist to the grant once `leave_grant()` returns. Because using a
493        // `EnteredGrantKernelManagedLayout` object is the only only way we
494        // access the actual memory of a grant, and we are calling
495        // `leave_grant()` from its `drop()` method, we are sure there will be
496        // no remaining references to the grant.
497        unsafe {
498            self.process.leave_grant(self.grant_num);
499        }
500    }
501}
502
503/// This [`GrantData`] object provides access to the memory allocated for a
504/// grant for a specific process.
505///
506/// The [`GrantData`] type is templated on `T`, the actual type of the object in
507/// the grant. [`GrantData'] holds a mutable reference to the type, allowing
508/// users access to the object in process memory.
509///
510/// Capsules gain access to a [`GrantData`] object by calling
511/// [`Grant::enter()`].
512pub struct GrantData<'a, T: 'a + ?Sized> {
513    /// The mutable reference to the actual object type stored in the grant.
514    data: &'a mut T,
515}
516
517impl<'a, T: 'a + ?Sized> GrantData<'a, T> {
518    /// Create a [`GrantData`] object to provide access to the actual object
519    /// allocated for a process.
520    ///
521    /// Only one can [`GrantData`] per underlying object can be created at a
522    /// time. Otherwise, there would be multiple mutable references to the same
523    /// object which is undefined behavior.
524    fn new(data: &'a mut T) -> GrantData<'a, T> {
525        GrantData { data }
526    }
527}
528
529impl<'a, T: 'a + ?Sized> Deref for GrantData<'a, T> {
530    type Target = T;
531    fn deref(&self) -> &T {
532        self.data
533    }
534}
535
536impl<'a, T: 'a + ?Sized> DerefMut for GrantData<'a, T> {
537    fn deref_mut(&mut self) -> &mut T {
538        self.data
539    }
540}
541
542/// This [`GrantKernelData`] object provides a handle to access upcalls and
543/// process buffers stored on behalf of a particular grant/driver.
544///
545/// Capsules gain access to a [`GrantKernelData`] object by calling
546/// [`Grant::enter()`]. From there, they can schedule upcalls or access process
547/// buffers.
548///
549/// It is expected that this type will only exist as a short-lived stack
550/// allocation, so its size is not a significant concern.
551pub struct GrantKernelData<'a> {
552    /// A reference to the actual upcall slice stored in the grant.
553    upcalls: &'a [SavedUpcall],
554
555    /// A reference to the actual read only allow slice stored in the grant.
556    allow_ro: &'a [SavedAllowRo],
557
558    /// A reference to the actual read write allow slice stored in the grant.
559    allow_rw: &'a [SavedAllowRw],
560
561    /// We need to keep track of the driver number so we can properly identify
562    /// the Upcall that is called. We need to keep track of its source so we can
563    /// remove it if the Upcall is unsubscribed.
564    driver_num: usize,
565
566    /// A reference to the process that these upcalls are for. This is used for
567    /// actually scheduling the upcalls.
568    process: &'a dyn Process,
569}
570
571impl<'a> GrantKernelData<'a> {
572    /// Create a [`GrantKernelData`] object to provide a handle for capsules to
573    /// call Upcalls.
574    fn new(
575        upcalls: &'a [SavedUpcall],
576        allow_ro: &'a [SavedAllowRo],
577        allow_rw: &'a [SavedAllowRw],
578        driver_num: usize,
579        process: &'a dyn Process,
580    ) -> GrantKernelData<'a> {
581        Self {
582            upcalls,
583            allow_ro,
584            allow_rw,
585            driver_num,
586            process,
587        }
588    }
589
590    /// Schedule the specified upcall for the process with r0, r1, r2 as
591    /// provided values.
592    ///
593    /// Capsules call this function to schedule upcalls, and upcalls are
594    /// identified by the `subscribe_num`, which must match the subscribe number
595    /// used when the upcall was originally subscribed by a process.
596    /// `subscribe_num`s are indexed starting at zero.
597    pub fn schedule_upcall(
598        &self,
599        subscribe_num: usize,
600        r: (usize, usize, usize),
601    ) -> Result<(), UpcallError> {
602        // Implement `self.upcalls[subscribe_num]` without a chance of a panic.
603        self.upcalls.get(subscribe_num).map_or(
604            Err(UpcallError::InvalidSubscribeNum),
605            |saved_upcall| {
606                // We can create an `Upcall` object based on what is stored in
607                // the process grant and use that to add the upcall to the
608                // pending array for the process.
609                let upcall = Upcall::new(
610                    self.process.processid(),
611                    UpcallId {
612                        subscribe_num,
613                        driver_num: self.driver_num,
614                    },
615                    saved_upcall.appdata,
616                    saved_upcall.fn_ptr,
617                );
618                upcall.schedule(self.process, r.0, r.1, r.2)
619            },
620        )
621    }
622
623    /// Search the work queue for the first pending operation with the given
624    /// `subscribe_num` and if one exists remove it from the task queue.
625    ///
626    /// Returns the associated [`Task`](crate::process::Task) if one was found, otherwise returns
627    /// [`None`].
628    pub fn remove_upcall(&self, subscribe_num: usize) -> Option<crate::process::Task> {
629        self.process.remove_upcall(UpcallId {
630            subscribe_num,
631            driver_num: self.driver_num,
632        })
633    }
634
635    /// Remove all scheduled upcalls with the given `subscribe_num` from the
636    /// task queue.
637    ///
638    /// Returns the number of removed upcalls.
639    pub fn remove_pending_upcalls(&self, subscribe_num: usize) -> usize {
640        self.process.remove_pending_upcalls(UpcallId {
641            subscribe_num,
642            driver_num: self.driver_num,
643        })
644    }
645
646    /// Returns a lifetime limited reference to the requested
647    /// [`ReadOnlyProcessBuffer`].
648    ///
649    /// The len of the returned [`ReadOnlyProcessBuffer`] must be checked by the
650    /// caller to ensure that a buffer has in fact been allocated. An
651    /// unallocated buffer will be returned as a [`ReadOnlyProcessBuffer`] of
652    /// length 0.
653    ///
654    /// The [`ReadOnlyProcessBuffer`] is only valid for as long as this object
655    /// is valid, i.e. the lifetime of the app enter closure.
656    ///
657    /// If the specified allow number is invalid, then a
658    /// [`crate::process::Error::AddressOutOfBounds`] will be returned. This
659    /// returns a [`crate::process::Error`] to allow for easy chaining of this
660    /// function with the `ReadOnlyProcessBuffer::enter()` function with
661    /// `and_then`.
662    pub fn get_readonly_processbuffer(
663        &self,
664        allow_ro_num: usize,
665    ) -> Result<ReadOnlyProcessBufferRef, crate::process::Error> {
666        self.allow_ro.get(allow_ro_num).map_or(
667            Err(crate::process::Error::AddressOutOfBounds),
668            |saved_ro| {
669                // # Safety
670                //
671                // This is the saved process buffer data has been validated to
672                // be wholly contained within this process before it was stored.
673                // The lifetime of the ReadOnlyProcessBuffer is bound to the
674                // lifetime of self, which correctly limits dereferencing this
675                // saved pointer to only when it is valid.
676                unsafe {
677                    Ok(ReadOnlyProcessBufferRef::new(
678                        saved_ro.ptr,
679                        saved_ro.len,
680                        self.process.processid(),
681                    ))
682                }
683            },
684        )
685    }
686
687    /// Returns a lifetime limited reference to the requested
688    /// [`ReadWriteProcessBuffer`].
689    ///
690    /// The length of the returned [`ReadWriteProcessBuffer`] must be checked by
691    /// the caller to ensure that a buffer has in fact been allocated. An
692    /// unallocated buffer will be returned as a [`ReadWriteProcessBuffer`] of
693    /// length 0.
694    ///
695    /// The [`ReadWriteProcessBuffer`] is only value for as long as this object
696    /// is valid, i.e. the lifetime of the app enter closure.
697    ///
698    /// If the specified allow number is invalid, then a
699    /// [`crate::process::Error::AddressOutOfBounds`] will be returned. This
700    /// returns a [`crate::process::Error`] to allow for easy chaining of this
701    /// function with the `ReadWriteProcessBuffer::enter()` function with
702    /// `and_then`.
703    pub fn get_readwrite_processbuffer(
704        &self,
705        allow_rw_num: usize,
706    ) -> Result<ReadWriteProcessBufferRef, crate::process::Error> {
707        self.allow_rw.get(allow_rw_num).map_or(
708            Err(crate::process::Error::AddressOutOfBounds),
709            |saved_rw| {
710                // # Safety
711                //
712                // This is the saved process buffer data has been validated to
713                // be wholly contained within this process before it was stored.
714                // The lifetime of the ReadWriteProcessBuffer is bound to the
715                // lifetime of self, which correctly limits dereferencing this
716                // saved pointer to only when it is valid.
717                unsafe {
718                    Ok(ReadWriteProcessBufferRef::new(
719                        saved_rw.ptr,
720                        saved_rw.len,
721                        self.process.processid(),
722                    ))
723                }
724            },
725        )
726    }
727}
728
729/// A minimal representation of an upcall, used for storing an upcall in a
730/// process' grant table without wasting memory duplicating information such as
731/// process ID.
732#[repr(C)]
733#[derive(Default)]
734struct SavedUpcall {
735    appdata: MachineRegister,
736    fn_ptr: CapabilityPtr,
737}
738
739/// A minimal representation of a read-only allow from app, used for storing a
740/// read-only allow in a process' kernel managed grant space without wasting
741/// memory duplicating information such as process ID.
742#[repr(C)]
743struct SavedAllowRo {
744    ptr: *const u8,
745    len: usize,
746}
747
748impl Default for SavedAllowRo {
749    fn default() -> Self {
750        Self {
751            ptr: core::ptr::null(),
752            len: 0,
753        }
754    }
755}
756
757/// A minimal representation of a read-write allow from app, used for storing a
758/// read-write allow in a process' kernel managed grant space without wasting
759/// memory duplicating information such as process ID.
760#[repr(C)]
761struct SavedAllowRw {
762    ptr: *mut u8,
763    len: usize,
764}
765
766impl Default for SavedAllowRw {
767    fn default() -> Self {
768        Self {
769            ptr: core::ptr::null_mut(),
770            len: 0,
771        }
772    }
773}
774
775/// Write the default value of T to every element of the array.
776///
777/// # Safety
778///
779/// The pointer must be well aligned and point to allocated memory that is
780/// writable for `size_of::<T> * num` bytes. No Rust references may exist to
781/// memory in the address range spanned by `base..base+num` at the time this
782/// function is called. The memory does not need to be initialized yet. If it
783/// already does contain initialized memory, then those contents will be
784/// overwritten without being `Drop`ed first.
785unsafe fn write_default_array<T: Default>(base: *mut T, num: usize) {
786    for i in 0..num {
787        base.add(i).write(T::default());
788    }
789}
790
791/// Enters the grant for the specified process. Caller must hold on to the grant
792/// lifetime guard while they accessing the memory in the layout (second
793/// element).
794fn enter_grant_kernel_managed(
795    process: &dyn Process,
796    driver_num: usize,
797) -> Result<EnteredGrantKernelManagedLayout, ErrorCode> {
798    let grant_num = process.lookup_grant_from_driver_num(driver_num)?;
799
800    // Check if the grant has been allocated, and if not we cannot enter this
801    // grant.
802    match process.grant_is_allocated(grant_num) {
803        Some(true) => { /* Allocated, nothing to do */ }
804        Some(false) => return Err(ErrorCode::NOMEM),
805        None => return Err(ErrorCode::FAIL),
806    }
807
808    // Return early if no grant.
809    let grant_base_ptr = process.enter_grant(grant_num).or(Err(ErrorCode::NOMEM))?;
810    // # Safety
811    //
812    // We know that this pointer is well aligned and initialized with meaningful
813    // data when the grant region was allocated.
814    let layout = unsafe {
815        EnteredGrantKernelManagedLayout::read_from_base(grant_base_ptr, process, grant_num)
816    };
817    Ok(layout)
818}
819
820/// Subscribe to an upcall by saving the upcall in the grant region for the
821/// process and returning the existing upcall for the same UpcallId.
822pub(crate) fn subscribe(
823    process: &dyn Process,
824    upcall: Upcall,
825) -> Result<Upcall, (Upcall, ErrorCode)> {
826    // Enter grant and keep it open until _grant_open goes out of scope.
827    let mut layout = match enter_grant_kernel_managed(process, upcall.upcall_id.driver_num) {
828        Ok(val) => val,
829        Err(e) => return Err((upcall, e)),
830    };
831
832    // Create the saved upcalls slice from the grant memory.
833    //
834    // # Safety
835    //
836    // This is safe because of how the grant was initially allocated and that
837    // because we were able to enter the grant the grant region must be valid
838    // and initialized. We are also holding the grant open until `_grant_open`
839    // goes out of scope.
840    let saved_upcalls_slice = layout.get_upcalls_slice();
841
842    // Index into the saved upcall slice to get the old upcall. Use .get in case
843    // userspace passed us a bad subscribe number.
844    match saved_upcalls_slice.get_mut(upcall.upcall_id.subscribe_num) {
845        Some(saved_upcall) => {
846            // Create an `Upcall` object with the old saved upcall.
847            let old_upcall = Upcall::new(
848                process.processid(),
849                upcall.upcall_id,
850                saved_upcall.appdata,
851                saved_upcall.fn_ptr,
852            );
853
854            // Overwrite the saved upcall with the new upcall.
855            saved_upcall.appdata = upcall.appdata;
856            saved_upcall.fn_ptr = upcall.fn_ptr;
857
858            // Success!
859            Ok(old_upcall)
860        }
861        None => Err((upcall, ErrorCode::NOSUPPORT)),
862    }
863}
864
865/// Stores the specified read-only process buffer in the kernel managed grant
866/// region for this process and driver. The previous read-only process buffer
867/// stored at the same allow_num id is returned.
868pub(crate) fn allow_ro(
869    process: &dyn Process,
870    driver_num: usize,
871    allow_num: usize,
872    buffer: ReadOnlyProcessBuffer,
873) -> Result<ReadOnlyProcessBuffer, (ReadOnlyProcessBuffer, ErrorCode)> {
874    // Enter grant and keep it open until `_grant_open` goes out of scope.
875    let mut layout = match enter_grant_kernel_managed(process, driver_num) {
876        Ok(val) => val,
877        Err(e) => return Err((buffer, e)),
878    };
879
880    // Create the saved allow ro slice from the grant memory.
881    //
882    // # Safety
883    //
884    // This is safe because of how the grant was initially allocated and that
885    // because we were able to enter the grant the grant region must be valid
886    // and initialized. We are also holding the grant open until _grant_open
887    // goes out of scope.
888    let saved_allow_ro_slice = layout.get_allow_ro_slice();
889
890    // Index into the saved slice to get the old value. Use .get in case
891    // userspace passed us a bad allow number.
892    match saved_allow_ro_slice.get_mut(allow_num) {
893        Some(saved) => {
894            // # Safety
895            //
896            // The pointer has already been validated to be within application
897            // memory before storing the values in the saved slice.
898            let old_allow =
899                unsafe { ReadOnlyProcessBuffer::new(saved.ptr, saved.len, process.processid()) };
900
901            // Replace old values with current buffer.
902            let (ptr, len) = buffer.consume();
903            saved.ptr = ptr;
904            saved.len = len;
905
906            // Success!
907            Ok(old_allow)
908        }
909        None => Err((buffer, ErrorCode::NOSUPPORT)),
910    }
911}
912
913/// Stores the specified read-write process buffer in the kernel managed grant
914/// region for this process and driver. The previous read-write process buffer
915/// stored at the same allow_num id is returned.
916pub(crate) fn allow_rw(
917    process: &dyn Process,
918    driver_num: usize,
919    allow_num: usize,
920    buffer: ReadWriteProcessBuffer,
921) -> Result<ReadWriteProcessBuffer, (ReadWriteProcessBuffer, ErrorCode)> {
922    // Enter grant and keep it open until `_grant_open` goes out of scope.
923    let mut layout = match enter_grant_kernel_managed(process, driver_num) {
924        Ok(val) => val,
925        Err(e) => return Err((buffer, e)),
926    };
927
928    // Create the saved allow rw slice from the grant memory.
929    //
930    // # Safety
931    //
932    // This is safe because of how the grant was initially allocated and that
933    // because we were able to enter the grant the grant region must be valid
934    // and initialized. We are also holding the grant open until `_grant_open`
935    // goes out of scope.
936    let saved_allow_rw_slice = layout.get_allow_rw_slice();
937
938    // Index into the saved slice to get the old value. Use .get in case
939    // userspace passed us a bad allow number.
940    match saved_allow_rw_slice.get_mut(allow_num) {
941        Some(saved) => {
942            // # Safety
943            //
944            // The pointer has already been validated to be within application
945            // memory before storing the values in the saved slice.
946            let old_allow =
947                unsafe { ReadWriteProcessBuffer::new(saved.ptr, saved.len, process.processid()) };
948
949            // Replace old values with current buffer.
950            let (ptr, len) = buffer.consume();
951            saved.ptr = ptr;
952            saved.len = len;
953
954            // Success!
955            Ok(old_allow)
956        }
957        None => Err((buffer, ErrorCode::NOSUPPORT)),
958    }
959}
960
961/// An instance of a grant allocated for a particular process.
962///
963/// [`ProcessGrant`] is a handle to an instance of a grant that has been
964/// allocated in a specific process's grant region. A [`ProcessGrant`]
965/// guarantees that the memory for the grant has been allocated in the process's
966/// memory.
967///
968/// This is created from a [`Grant`] when that grant is entered for a specific
969/// process.
970pub struct ProcessGrant<
971    'a,
972    T: 'a,
973    Upcalls: UpcallSize,
974    AllowROs: AllowRoSize,
975    AllowRWs: AllowRwSize,
976> {
977    /// The process the grant is applied to.
978    ///
979    /// We use a reference here because instances of [`ProcessGrant`] are very
980    /// short lived. They only exist while a [`Grant`] is being entered, so we
981    /// can be sure the process still exists while a `ProcessGrant` exists. No
982    /// [`ProcessGrant`] can be stored.
983    process: &'a dyn Process,
984
985    /// The syscall driver number this grant is associated with.
986    driver_num: usize,
987
988    /// The identifier of the Grant this is applied for.
989    grant_num: usize,
990
991    /// Used to store Rust types for grant.
992    _phantom: PhantomData<(T, Upcalls, AllowROs, AllowRWs)>,
993}
994
995impl<'a, T: Default, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: AllowRwSize>
996    ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>
997{
998    /// Create a [`ProcessGrant`] for the given Grant in the given Process's
999    /// grant region.
1000    ///
1001    /// If the grant in this process has not been setup before this will attempt
1002    /// to allocate the memory from the process's grant region.
1003    ///
1004    /// # Return
1005    ///
1006    /// If the grant is already allocated or could be allocated, and the process
1007    /// is valid, this returns `Ok(ProcessGrant)`. Otherwise it returns a
1008    /// relevant error.
1009    fn new(
1010        grant: &Grant<T, Upcalls, AllowROs, AllowRWs>,
1011        processid: ProcessId,
1012    ) -> Result<Self, Error> {
1013        // Moves non-generic code from new() into non-generic function to reduce
1014        // code bloat from the generic function being monomorphized, as it is
1015        // common to have over 50 copies of Grant::enter() in a Tock kernel (and
1016        // thus 50+ copies of this function). The returned Option indicates if
1017        // the returned pointer still needs to be initialized (in the case where
1018        // the grant was only just allocated).
1019        fn new_inner<'a>(
1020            grant_num: usize,
1021            driver_num: usize,
1022            grant_t_size: GrantDataSize,
1023            grant_t_align: GrantDataAlign,
1024            num_upcalls: UpcallItems,
1025            num_allow_ros: AllowRoItems,
1026            num_allow_rws: AllowRwItems,
1027            processid: ProcessId,
1028        ) -> Result<(Option<NonNull<u8>>, &'a dyn Process), Error> {
1029            // Here is an example of how the grants are laid out in the grant
1030            // region of process's memory:
1031            //
1032            // Mem. Addr.
1033            // 0x0040000  ┌────────────────────────────────────
1034            //            │   DriverNumN    [0x1]
1035            //            │   GrantPointerN [0x003FFC8]
1036            //            │   ...
1037            //            │   DriverNum1    [0x60000]
1038            //            │   GrantPointer1 [0x003FFC0]
1039            //            │   DriverNum0
1040            //            │   GrantPointer0 [0x0000000 (NULL)]
1041            //            ├────────────────────────────────────
1042            //            │   Process Control Block
1043            // 0x003FFE0  ├────────────────────────────────────  Grant Region ┐
1044            //            │   GrantDataN                                      │
1045            // 0x003FFC8  ├────────────────────────────────────               │
1046            //            │   GrantData1                                      ▼
1047            // 0x003FF20  ├────────────────────────────────────
1048            //            │
1049            //            │   --unallocated--
1050            //            │
1051            //            └────────────────────────────────────
1052            //
1053            // An array of pointers (one per possible grant region) point to
1054            // where the actual grant memory is allocated inside of the process.
1055            // The grant memory is not allocated until the actual grant region
1056            // is actually used.
1057
1058            let process = processid
1059                .kernel
1060                .get_process(processid)
1061                .ok_or(Error::NoSuchApp)?;
1062
1063            // Check if the grant is allocated. If not, we allocate it process
1064            // memory first. We then create an `ProcessGrant` object for this
1065            // grant.
1066            if let Some(is_allocated) = process.grant_is_allocated(grant_num) {
1067                if !is_allocated {
1068                    // Calculate the alignment and size for entire grant region.
1069                    let alloc_align = EnteredGrantKernelManagedLayout::grant_align(grant_t_align);
1070                    let alloc_size = EnteredGrantKernelManagedLayout::grant_size(
1071                        num_upcalls,
1072                        num_allow_ros,
1073                        num_allow_rws,
1074                        grant_t_size,
1075                        grant_t_align,
1076                    );
1077
1078                    // Allocate grant, the memory is still uninitialized though.
1079                    if process
1080                        .allocate_grant(grant_num, driver_num, alloc_size, alloc_align)
1081                        .is_err()
1082                    {
1083                        return Err(Error::OutOfMemory);
1084                    }
1085
1086                    let grant_ptr = process.enter_grant(grant_num)?;
1087
1088                    // Create a layout from the counts we have and initialize
1089                    // all memory so it is valid in the future to read as a
1090                    // reference.
1091                    //
1092                    // # Safety
1093                    //
1094                    // - The grant base pointer is well aligned, yet does not
1095                    //   have initialized data.
1096                    // - The pointer points to a large enough space to correctly
1097                    //   write to is guaranteed by alloc of size
1098                    //   `EnteredGrantKernelManagedLayout::grant_size`.
1099                    // - There are no proper rust references that map to these
1100                    //   addresses.
1101                    unsafe {
1102                        let _layout = EnteredGrantKernelManagedLayout::initialize_from_counts(
1103                            grant_ptr,
1104                            num_upcalls,
1105                            num_allow_ros,
1106                            num_allow_rws,
1107                            process,
1108                            grant_num,
1109                        );
1110                    }
1111
1112                    // # Safety
1113                    //
1114                    // The grant pointer points to an alloc that is alloc_size
1115                    // large and is at least as aligned as grant_t_align.
1116                    unsafe {
1117                        Ok((
1118                            Some(EnteredGrantKernelManagedLayout::offset_of_grant_data_t(
1119                                grant_ptr,
1120                                alloc_size,
1121                                grant_t_size,
1122                            )),
1123                            process,
1124                        ))
1125                    }
1126                } else {
1127                    // T was already allocated, outer function should not
1128                    // initialize T.
1129                    Ok((None, process))
1130                }
1131            } else {
1132                // Cannot use the grant region in any way if the process is
1133                // inactive.
1134                Err(Error::InactiveApp)
1135            }
1136        }
1137
1138        // Handle the bulk of the work in a function which is not templated.
1139        let (opt_raw_grant_ptr_nn, process) = new_inner(
1140            grant.grant_num,
1141            grant.driver_num,
1142            GrantDataSize(size_of::<T>()),
1143            GrantDataAlign(align_of::<T>()),
1144            UpcallItems(Upcalls::COUNT),
1145            AllowRoItems(AllowROs::COUNT),
1146            AllowRwItems(AllowRWs::COUNT),
1147            processid,
1148        )?;
1149
1150        // We can now do the initialization of T object if necessary.
1151        if let Some(allocated_ptr) = opt_raw_grant_ptr_nn {
1152            // Grant type T
1153            //
1154            // # Safety
1155            //
1156            // This is safe because:
1157            //
1158            // 1. The pointer address is valid. The pointer is allocated
1159            //    statically in process memory, and will exist for as long
1160            //    as the process does. The grant is only accessible while
1161            //    the process is still valid.
1162            //
1163            // 2. The pointer is correctly aligned. The newly allocated
1164            //    grant is aligned for type T, and there is padding inserted
1165            //    between the upcall array and the T object such that the T
1166            //    object starts a multiple of `align_of<T>` from the
1167            //    beginning of the allocation.
1168            unsafe {
1169                // Convert untyped `*mut u8` allocation to allocated type.
1170                let new_region = NonNull::cast::<T>(allocated_ptr);
1171                // We use `ptr::write` to avoid `Drop`ping the uninitialized
1172                // memory in case `T` implements the `Drop` trait.
1173                write(new_region.as_ptr(), T::default());
1174            }
1175        }
1176
1177        // We have ensured the grant is already allocated or was just allocated,
1178        // so we can create and return the `ProcessGrant` type.
1179        Ok(ProcessGrant {
1180            process,
1181            driver_num: grant.driver_num,
1182            grant_num: grant.grant_num,
1183            _phantom: PhantomData,
1184        })
1185    }
1186
1187    /// Return a [`ProcessGrant`] for a grant in a process if the process is
1188    /// valid and that process grant has already been allocated, or `None`
1189    /// otherwise.
1190    fn new_if_allocated(
1191        grant: &Grant<T, Upcalls, AllowROs, AllowRWs>,
1192        process: &'a dyn Process,
1193    ) -> Option<Self> {
1194        if let Some(is_allocated) = process.grant_is_allocated(grant.grant_num) {
1195            if is_allocated {
1196                Some(ProcessGrant {
1197                    process,
1198                    driver_num: grant.driver_num,
1199                    grant_num: grant.grant_num,
1200                    _phantom: PhantomData,
1201                })
1202            } else {
1203                // Grant has not been allocated.
1204                None
1205            }
1206        } else {
1207            // Process is invalid.
1208            None
1209        }
1210    }
1211
1212    /// Return the [`ProcessId`] of the process this [`ProcessGrant`] is
1213    /// associated with.
1214    pub fn processid(&self) -> ProcessId {
1215        self.process.processid()
1216    }
1217
1218    /// Run a function with access to the memory in the related process for the
1219    /// related Grant. This also provides access to any associated Upcalls and
1220    /// allowed buffers stored with the grant.
1221    ///
1222    /// This is "entering" the grant region, and the _only_ time when the
1223    /// contents of a grant region can be accessed.
1224    ///
1225    /// Note, a grant can only be entered once at a time. Attempting to call
1226    /// `.enter()` on a grant while it is already entered will result in a
1227    /// `panic!()`. See the comment in `access_grant()` for more information.
1228    pub fn enter<F, R>(self, fun: F) -> R
1229    where
1230        F: FnOnce(&mut GrantData<T>, &GrantKernelData) -> R,
1231    {
1232        // # `unwrap()` Safety
1233        //
1234        // `access_grant()` can only return `None` if the grant is already
1235        // entered. Since we are asking for a panic!() if the grant is entered,
1236        // `access_grant()` function will never return `None`.
1237        self.access_grant(fun, true).unwrap()
1238    }
1239
1240    /// Run a function with access to the data in the related process for the
1241    /// related Grant only if that grant region is not already entered. If the
1242    /// grant is already entered silently skip it. Also provide access to
1243    /// associated Upcalls.
1244    ///
1245    /// **You almost certainly should use `.enter()` rather than
1246    /// `.try_enter()`.**
1247    ///
1248    /// While the `.enter()` version can panic, that panic likely indicates a
1249    /// bug in the code and not a condition that should be handled. For example,
1250    /// this benign looking code is wrong:
1251    ///
1252    /// ```ignore
1253    /// self.apps.enter(thisapp, |app_grant, _| {
1254    ///     // Update state in the grant region of `thisapp`. Also, mark that
1255    ///     // `thisapp` needs to run again.
1256    ///     app_grant.runnable = true;
1257    ///
1258    ///     // Now, check all apps to see if any are ready to run.
1259    ///     let mut work_left_to_do = false;
1260    ///     self.apps.iter().each(|other_app| {
1261    ///         other_app.enter(|other_app_grant, _| { // ERROR! This leads to a
1262    ///             if other_app_grant.runnable {      // grant being entered
1263    ///                 work_left_to_do = true;        // twice!
1264    ///             }
1265    ///         })
1266    ///     })
1267    /// })
1268    /// ```
1269    ///
1270    /// The example is wrong because it tries to iterate across all grant
1271    /// regions while one of them is already entered. This will lead to a grant
1272    /// region being entered twice which violates Rust's memory restrictions and
1273    /// is undefined behavior.
1274    ///
1275    /// However, since the example uses `.enter()` on the iteration, Tock will
1276    /// panic when the grant is entered for the second time, notifying the
1277    /// developer that something is wrong. The fix is to exit out of the first
1278    /// `.enter()` before attempting to iterate over the grant for all
1279    /// processes.
1280    ///
1281    /// However, if the example used `.try_enter()` in the iter loop, there
1282    /// would be no panic, but the already entered grant would be silently
1283    /// skipped. This can hide subtle bugs if the skipped grant is only relevant
1284    /// in certain cases.
1285    ///
1286    /// Therefore, only use `try_enter()` if you are sure you want to skip the
1287    /// already entered grant. Cases for this are rare.
1288    ///
1289    /// ## Return
1290    ///
1291    /// Returns `None` if the grant is already entered. Otherwise returns
1292    /// `Some(fun())`.
1293    pub fn try_enter<F, R>(self, fun: F) -> Option<R>
1294    where
1295        F: FnOnce(&mut GrantData<T>, &GrantKernelData) -> R,
1296    {
1297        self.access_grant(fun, false)
1298    }
1299
1300    /// Run a function with access to the memory in the related process for the
1301    /// related Grant. Also provide this function with access to any associated
1302    /// Upcalls and an allocator for allocating additional memory in the
1303    /// process's grant region.
1304    ///
1305    /// This is "entering" the grant region, and the _only_ time when the
1306    /// contents of a grant region can be accessed.
1307    ///
1308    /// Note, a grant can only be entered once at a time. Attempting to call
1309    /// `.enter()` on a grant while it is already entered will result in a
1310    /// panic!()`. See the comment in `access_grant()` for more information.
1311    pub fn enter_with_allocator<F, R>(self, fun: F) -> R
1312    where
1313        F: FnOnce(&mut GrantData<T>, &GrantKernelData, &mut GrantRegionAllocator) -> R,
1314    {
1315        // # `unwrap()` Safety
1316        //
1317        // `access_grant()` can only return `None` if the grant is already
1318        // entered. Since we are asking for a panic!() if the grant is entered,
1319        // `access_grant()` function will never return `None`.
1320        self.access_grant_with_allocator(fun, true).unwrap()
1321    }
1322
1323    /// Access the [`ProcessGrant`] memory and run a closure on the process's
1324    /// grant memory.
1325    ///
1326    /// If `panic_on_reenter` is `true`, this will panic if the grant region is
1327    /// already currently entered. If `panic_on_reenter` is `false`, this will
1328    /// return `None` if the grant region is entered and do nothing.
1329    fn access_grant<F, R>(self, fun: F, panic_on_reenter: bool) -> Option<R>
1330    where
1331        F: FnOnce(&mut GrantData<T>, &GrantKernelData) -> R,
1332    {
1333        self.access_grant_with_allocator(
1334            |grant_data, kernel_data, _allocator| fun(grant_data, kernel_data),
1335            panic_on_reenter,
1336        )
1337    }
1338
1339    /// Access the [`ProcessGrant`] memory and run a closure on the process's
1340    /// grant memory.
1341    ///
1342    /// If `panic_on_reenter` is `true`, this will panic if the grant region is
1343    /// already currently entered. If `panic_on_reenter` is `false`, this will
1344    /// return `None` if the grant region is entered and do nothing.
1345    fn access_grant_with_allocator<F, R>(self, fun: F, panic_on_reenter: bool) -> Option<R>
1346    where
1347        F: FnOnce(&mut GrantData<T>, &GrantKernelData, &mut GrantRegionAllocator) -> R,
1348    {
1349        // Access the grant that is in process memory. This can only fail if
1350        // the grant is already entered.
1351        let grant_ptr = self
1352            .process
1353            .enter_grant(self.grant_num)
1354            .map_err(|_err| {
1355                // If we get an error it is because the grant is already
1356                // entered. `process.enter_grant()` can fail for several
1357                // reasons, but only the double enter case can happen once a
1358                // grant has been applied. The other errors would be detected
1359                // earlier (i.e. before the grant can be applied).
1360
1361                // If `panic_on_reenter` is false, we skip this error and do
1362                // nothing with this grant.
1363                if !panic_on_reenter {
1364                    return;
1365                }
1366
1367                // If `enter_grant` fails, we panic!() to notify the developer
1368                // that they tried to enter the same grant twice which is
1369                // prohibited because it would result in two mutable references
1370                // existing for the same memory. This preserves type correctness
1371                // (but does crash the system).
1372                //
1373                // ## Explanation and Rationale
1374                //
1375                // This panic represents a tradeoff. While it is undesirable to
1376                // have the potential for a runtime crash in this grant region
1377                // code, it balances usability with type correctness. The
1378                // challenge is that calling `self.apps.iter()` is a common
1379                // pattern in capsules to access the grant region of every app
1380                // that is using the capsule, and sometimes it is intuitive to
1381                // call that inside of a `self.apps.enter(processid, |app| {...})`
1382                // closure. However, `.enter()` means that app's grant region is
1383                // entered, and then a naive `.iter()` would re-enter the grant
1384                // region and cause undefined behavior. We considered different
1385                // options to resolve this.
1386                //
1387                // 1. Have `.iter()` only iterate over grant regions which are
1388                //    not entered. This avoids the bug, but could lead to
1389                //    unexpected behavior, as `self.apps.iter()` will do
1390                //    different things depending on where in a capsule it is
1391                //    called.
1392                // 2. Have the compiler detect when `.iter()` is called when a
1393                //    grant region has already been entered. We don't know of a
1394                //    viable way to implement this.
1395                // 3. Panic if `.iter()` is called when a grant is already
1396                //    entered.
1397                //
1398                // We decided on option 3 because it balances minimizing
1399                // surprises (`self.apps.iter()` will always iterate all grants)
1400                // while also protecting against the bug. We expect that any
1401                // code that attempts to call `self.apps.iter()` after calling
1402                // `.enter()` will immediately encounter this `panic!()` and
1403                // have to be refactored before any tests will be successful.
1404                // Therefore, this `panic!()` should only occur at
1405                // development/testing time.
1406                //
1407                // ## How to fix this error
1408                //
1409                // If you are seeing this panic, you need to refactor your
1410                // capsule to not call `.iter()` or `.each()` from inside a
1411                // `.enter()` closure. That is, you need to close the grant
1412                // region you are currently in before trying to iterate over all
1413                // grant regions.
1414                panic!("Attempted to re-enter a grant region.");
1415            })
1416            .ok()?;
1417        let grant_t_align = GrantDataAlign(align_of::<T>());
1418        let grant_t_size = GrantDataSize(size_of::<T>());
1419
1420        let alloc_size = EnteredGrantKernelManagedLayout::grant_size(
1421            UpcallItems(Upcalls::COUNT),
1422            AllowRoItems(AllowROs::COUNT),
1423            AllowRwItems(AllowRWs::COUNT),
1424            grant_t_size,
1425            grant_t_align,
1426        );
1427
1428        // Parse layout of entire grant allocation using the known base pointer.
1429        //
1430        // # Safety
1431        //
1432        // Grant pointer is well aligned and points to initialized data.
1433        let layout = unsafe {
1434            EnteredGrantKernelManagedLayout::read_from_base(grant_ptr, self.process, self.grant_num)
1435        };
1436
1437        // Get references to all of the saved upcall data.
1438        //
1439        // # Safety
1440        //
1441        // - Pointer is well aligned and initialized with data from Self::new()
1442        //   call.
1443        // - Data will not be modified externally while this immutable reference
1444        //   is alive.
1445        // - Data is accessible for the entire duration of this immutable
1446        //   reference.
1447        // - No other mutable reference to this memory exists concurrently.
1448        //   Mutable reference to this memory are only created through the
1449        //   kernel in the syscall interface which is serialized in time with
1450        //   this call.
1451        let (saved_upcalls_slice, saved_allow_ro_slice, saved_allow_rw_slice) =
1452            layout.get_resource_slices();
1453        let grant_data = unsafe {
1454            EnteredGrantKernelManagedLayout::offset_of_grant_data_t(
1455                grant_ptr,
1456                alloc_size,
1457                grant_t_size,
1458            )
1459            .cast()
1460            .as_mut()
1461        };
1462
1463        // Create a wrapped objects that are passed to functor.
1464        let mut grant_data = GrantData::new(grant_data);
1465        let kernel_data = GrantKernelData::new(
1466            saved_upcalls_slice,
1467            saved_allow_ro_slice,
1468            saved_allow_rw_slice,
1469            self.driver_num,
1470            self.process,
1471        );
1472        // Setup an allocator in case the capsule needs additional memory in the
1473        // grant space.
1474        let mut allocator = GrantRegionAllocator {
1475            processid: self.process.processid(),
1476        };
1477
1478        // Call functor and pass back value.
1479        Some(fun(&mut grant_data, &kernel_data, &mut allocator))
1480    }
1481}
1482
1483/// Grant which was allocated from the kernel-owned grant region in a specific
1484/// process's memory, separately from a normal `Grant`.
1485///
1486/// A [`CustomGrant`] allows a capsule to allocate additional memory on behalf
1487/// of a process.
1488pub struct CustomGrant<T> {
1489    /// An identifier for this custom grant within a process's grant region.
1490    ///
1491    /// Here, this is an opaque reference that Process uses to access the
1492    /// custom grant allocation. This setup ensures that Process owns the grant
1493    /// memory.
1494    identifier: ProcessCustomGrantIdentifier,
1495
1496    /// Identifier for the process where this custom grant is allocated.
1497    processid: ProcessId,
1498
1499    /// Used to keep the Rust type of the grant.
1500    _phantom: PhantomData<T>,
1501}
1502
1503impl<T> CustomGrant<T> {
1504    /// Creates a new [`CustomGrant`].
1505    fn new(identifier: ProcessCustomGrantIdentifier, processid: ProcessId) -> Self {
1506        CustomGrant {
1507            identifier,
1508            processid,
1509            _phantom: PhantomData,
1510        }
1511    }
1512
1513    /// Helper function to get the [`ProcessId`] from the custom grant.
1514    pub fn processid(&self) -> ProcessId {
1515        self.processid
1516    }
1517
1518    /// Gives access to inner data within the given closure.
1519    ///
1520    /// If the process has since been restarted or crashed, or the memory is
1521    /// otherwise no longer present, then this function will not call the given
1522    /// closure, and will instead directly return `Err(Error::NoSuchApp)`.
1523    ///
1524    /// Because this function requires `&mut self`, it should be impossible to
1525    /// access the inner data of a given `CustomGrant` reentrantly. Thus the
1526    /// reentrance detection we use for non-custom grants is not needed here.
1527    pub fn enter<F, R>(&self, fun: F) -> Result<R, Error>
1528    where
1529        F: FnOnce(GrantData<'_, T>) -> R,
1530    {
1531        // Verify that the process this CustomGrant was allocated within still
1532        // exists.
1533        self.processid
1534            .kernel
1535            .process_map_or(Err(Error::NoSuchApp), self.processid, |process| {
1536                // App is valid.
1537
1538                // Now try to access the custom grant memory.
1539                let grant_ptr = process.enter_custom_grant(self.identifier)?;
1540
1541                // # Safety
1542                //
1543                // `grant_ptr` must be a valid pointer and there must not exist
1544                // any other references to the same memory. We verify the
1545                // pointer is valid and aligned when the memory is allocated and
1546                // `CustomGrant` is created. We are sure that there are no
1547                // other references because the only way to create a reference
1548                // is using this `enter()` function, and it can only be called
1549                // once (because of the `&mut self` requirement).
1550                let custom_grant = unsafe { &mut *(grant_ptr as *mut T) };
1551                let borrowed = GrantData::new(custom_grant);
1552                Ok(fun(borrowed))
1553            })
1554    }
1555}
1556
1557/// Tool for allocating additional memory regions in a process's grant region.
1558///
1559/// This is optionally provided along with a grant so that if a capsule needs
1560/// per-process dynamic allocation it can allocate additional memory.
1561pub struct GrantRegionAllocator {
1562    /// The process the allocator will allocate memory from.
1563    processid: ProcessId,
1564}
1565
1566impl GrantRegionAllocator {
1567    /// Allocates a new [`CustomGrant`] initialized using the given closure.
1568    ///
1569    /// The closure will be called exactly once, and the result will be used to
1570    /// initialize the owned value.
1571    ///
1572    /// This interface was chosen instead of a simple `alloc(val)` as it's
1573    /// much more likely to optimize out all stack intermediates. This
1574    /// helps to prevent stack overflows when allocating large values.
1575    ///
1576    /// # Panic Safety
1577    ///
1578    /// If `init` panics, the freshly allocated memory may leak.
1579    pub fn alloc_with<T, F>(&self, init: F) -> Result<CustomGrant<T>, Error>
1580    where
1581        F: FnOnce() -> T,
1582    {
1583        let (custom_grant_identifier, typed_ptr) = self.alloc_raw::<T>()?;
1584
1585        // # Safety
1586        //
1587        // Writing to this pointer is safe as long as the pointer is valid
1588        // and aligned. `alloc_raw()` guarantees these constraints are met.
1589        unsafe {
1590            // We use `ptr::write` to avoid `Drop`ping the uninitialized memory
1591            // in case `T` implements the `Drop` trait.
1592            write(typed_ptr.as_ptr(), init());
1593        }
1594
1595        Ok(CustomGrant::new(custom_grant_identifier, self.processid))
1596    }
1597
1598    /// Allocates a slice of n instances of a given type. Each instance is
1599    /// initialized using the provided function.
1600    ///
1601    /// The provided function will be called exactly `n` times, and will be
1602    /// passed the index it's initializing, from `0` through `NUM_ITEMS - 1`.
1603    ///
1604    /// # Panic Safety
1605    ///
1606    /// If `val_func` panics, the freshly allocated memory and any values
1607    /// already written will be leaked.
1608    pub fn alloc_n_with<T, F, const NUM_ITEMS: usize>(
1609        &self,
1610        mut init: F,
1611    ) -> Result<CustomGrant<[T; NUM_ITEMS]>, Error>
1612    where
1613        F: FnMut(usize) -> T,
1614    {
1615        let (custom_grant_identifier, typed_ptr) = self.alloc_n_raw::<T>(NUM_ITEMS)?;
1616
1617        for i in 0..NUM_ITEMS {
1618            // # Safety
1619            //
1620            // The allocate function guarantees that `ptr` points to memory
1621            // large enough to allocate `num_items` copies of the object.
1622            unsafe {
1623                write(typed_ptr.as_ptr().add(i), init(i));
1624            }
1625        }
1626
1627        Ok(CustomGrant::new(custom_grant_identifier, self.processid))
1628    }
1629
1630    /// Allocates uninitialized grant memory appropriate to store a `T`.
1631    ///
1632    /// The caller must initialize the memory.
1633    ///
1634    /// Also returns a ProcessCustomGrantIdentifier to access the memory later.
1635    fn alloc_raw<T>(&self) -> Result<(ProcessCustomGrantIdentifier, NonNull<T>), Error> {
1636        self.alloc_n_raw::<T>(1)
1637    }
1638
1639    /// Allocates space for a dynamic number of items.
1640    ///
1641    /// The caller is responsible for initializing the returned memory.
1642    ///
1643    /// Returns memory appropriate for storing `num_items` contiguous instances
1644    /// of `T` and a ProcessCustomGrantIdentifier to access the memory later.
1645    fn alloc_n_raw<T>(
1646        &self,
1647        num_items: usize,
1648    ) -> Result<(ProcessCustomGrantIdentifier, NonNull<T>), Error> {
1649        let (custom_grant_identifier, raw_ptr) =
1650            self.alloc_n_raw_inner(num_items, size_of::<T>(), align_of::<T>())?;
1651        let typed_ptr = NonNull::cast::<T>(raw_ptr);
1652
1653        Ok((custom_grant_identifier, typed_ptr))
1654    }
1655
1656    /// Helper to reduce code bloat by avoiding monomorphization.
1657    fn alloc_n_raw_inner(
1658        &self,
1659        num_items: usize,
1660        single_alloc_size: usize,
1661        alloc_align: usize,
1662    ) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), Error> {
1663        let alloc_size = single_alloc_size
1664            .checked_mul(num_items)
1665            .ok_or(Error::OutOfMemory)?;
1666        self.processid
1667            .kernel
1668            .process_map_or(Err(Error::NoSuchApp), self.processid, |process| {
1669                process
1670                    .allocate_custom_grant(alloc_size, alloc_align)
1671                    .map_or(
1672                        Err(Error::OutOfMemory),
1673                        |(custom_grant_identifier, raw_ptr)| Ok((custom_grant_identifier, raw_ptr)),
1674                    )
1675            })
1676    }
1677}
1678
1679/// Type for storing an object of type T in process memory that is only
1680/// accessible by the kernel.
1681///
1682/// A single [`Grant`] can allocate space for one object of type T for each
1683/// process on the board. Each allocated object will reside in the grant region
1684/// belonging to the process that the object is allocated for. The [`Grant`]
1685/// type is used to get access to [`ProcessGrant`]s, which are tied to a
1686/// specific process and provide access to the memory object allocated for that
1687/// process.
1688pub struct Grant<T: Default, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: AllowRwSize> {
1689    /// Hold a reference to the core kernel so we can iterate processes.
1690    pub(crate) kernel: &'static Kernel,
1691
1692    /// Keep track of the syscall driver number assigned to the capsule that is
1693    /// using this grant. This allows us to uniquely identify upcalls stored in
1694    /// this grant.
1695    driver_num: usize,
1696
1697    /// The identifier for this grant. Having an identifier allows the Process
1698    /// implementation to lookup the memory for this grant in the specific
1699    /// process.
1700    grant_num: usize,
1701
1702    /// Used to store the Rust types for grant.
1703    ptr: PhantomData<(T, Upcalls, AllowROs, AllowRWs)>,
1704}
1705
1706impl<T: Default, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: AllowRwSize>
1707    Grant<T, Upcalls, AllowROs, AllowRWs>
1708{
1709    /// Create a new [`Grant`] type which allows a capsule to store
1710    /// process-specific data for each process in the process's memory region.
1711    ///
1712    /// This must only be called from the main kernel so that it can ensure that
1713    /// `grant_index` is a valid index.
1714    pub(crate) fn new(kernel: &'static Kernel, driver_num: usize, grant_index: usize) -> Self {
1715        Self {
1716            kernel,
1717            driver_num,
1718            grant_num: grant_index,
1719            ptr: PhantomData,
1720        }
1721    }
1722
1723    /// Enter the grant for a specific process.
1724    ///
1725    /// This creates a [`ProcessGrant`] which is a handle for a grant allocated
1726    /// for a specific process. Then, that [`ProcessGrant`] is entered and the
1727    /// provided closure is run with access to the memory in the grant region.
1728    pub fn enter<F, R>(&self, processid: ProcessId, fun: F) -> Result<R, Error>
1729    where
1730        F: FnOnce(&mut GrantData<T>, &GrantKernelData) -> R,
1731    {
1732        let pg = ProcessGrant::new(self, processid)?;
1733
1734        // If we have managed to create an `ProcessGrant`, all we need
1735        // to do is actually access the memory and run the
1736        // capsule-provided closure. This can only fail if the grant is
1737        // already entered, at which point the kernel will panic.
1738        Ok(pg.enter(fun))
1739    }
1740
1741    /// Enter the grant for a specific process with access to an allocator.
1742    ///
1743    /// This creates an [`ProcessGrant`] which is a handle for a grant allocated
1744    /// for a specific process. Then, that [`ProcessGrant`] is entered and the
1745    /// provided closure is run with access to the memory in the grant region.
1746    ///
1747    /// The allocator allows the caller to dynamically allocate additional
1748    /// memory in the process's grant region.
1749    pub fn enter_with_allocator<F, R>(&self, processid: ProcessId, fun: F) -> Result<R, Error>
1750    where
1751        F: FnOnce(&mut GrantData<T>, &GrantKernelData, &mut GrantRegionAllocator) -> R,
1752    {
1753        // Get the `ProcessGrant` for the process, possibly needing to
1754        // actually allocate the memory in the process's grant region to
1755        // do so. This can fail for a variety of reasons, and if so we
1756        // return the error to the capsule.
1757        let pg = ProcessGrant::new(self, processid)?;
1758
1759        // If we have managed to create an `ProcessGrant`, all we need
1760        // to do is actually access the memory and run the
1761        // capsule-provided closure. This can only fail if the grant is
1762        // already entered, at which point the kernel will panic.
1763        Ok(pg.enter_with_allocator(fun))
1764    }
1765
1766    /// Run a function on the grant for each active process if the grant has
1767    /// been allocated for that process.
1768    ///
1769    /// This will silently skip any process where the grant has not previously
1770    /// been allocated. This will also silently skip any invalid processes.
1771    ///
1772    /// Calling this function when an [`ProcessGrant`] for a process is
1773    /// currently entered will result in a panic.
1774    pub fn each<F>(&self, mut fun: F)
1775    where
1776        F: FnMut(ProcessId, &mut GrantData<T>, &GrantKernelData),
1777    {
1778        // Create a the iterator across `ProcessGrant`s for each process.
1779        for pg in self.iter() {
1780            let processid = pg.processid();
1781            // Since we iterating, there is no return value we need to worry
1782            // about.
1783            pg.enter(|data, upcalls| fun(processid, data, upcalls));
1784        }
1785    }
1786
1787    /// Get an iterator over all processes and their active grant regions for
1788    /// this particular grant.
1789    ///
1790    /// Calling this function when an [`ProcessGrant`] for a process is
1791    /// currently entered will result in a panic.
1792    pub fn iter(&self) -> Iter<T, Upcalls, AllowROs, AllowRWs> {
1793        Iter {
1794            grant: self,
1795            subiter: self.kernel.get_process_iter(),
1796        }
1797    }
1798}
1799
1800/// Type to iterate [`ProcessGrant`]s across processes.
1801pub struct Iter<
1802    'a,
1803    T: 'a + Default,
1804    Upcalls: UpcallSize,
1805    AllowROs: AllowRoSize,
1806    AllowRWs: AllowRwSize,
1807> {
1808    /// The grant type to use.
1809    grant: &'a Grant<T, Upcalls, AllowROs, AllowRWs>,
1810
1811    /// Iterator over valid processes.
1812    subiter: core::iter::FilterMap<
1813        core::slice::Iter<'a, Option<&'static dyn Process>>,
1814        fn(&Option<&'static dyn Process>) -> Option<&'static dyn Process>,
1815    >,
1816}
1817
1818impl<'a, T: Default, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: AllowRwSize> Iterator
1819    for Iter<'a, T, Upcalls, AllowROs, AllowRWs>
1820{
1821    type Item = ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>;
1822
1823    fn next(&mut self) -> Option<Self::Item> {
1824        let grant = self.grant;
1825        // Get the next `ProcessId` from the kernel processes array that is
1826        // setup to use this grant. Since the iterator itself is saved calling
1827        // this function again will start where we left off.
1828        self.subiter
1829            .find_map(|process| ProcessGrant::new_if_allocated(grant, process))
1830    }
1831}