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