Skip to main content

kernel/
process_standard.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//! Tock default Process implementation.
6//!
7//! `ProcessStandard` is an implementation for a userspace process running on
8//! the Tock kernel.
9
10use core::cell::Cell;
11use core::cmp;
12use core::fmt::Write;
13use core::mem::MaybeUninit;
14use core::num::NonZeroU32;
15use core::ptr::NonNull;
16use core::{mem, ptr, slice, str};
17
18use crate::collections::queue::Queue;
19use crate::collections::ring_buffer::RingBuffer;
20use crate::config;
21use crate::debug;
22use crate::errorcode::ErrorCode;
23use crate::init_uninit_struct;
24use crate::kernel::Kernel;
25use crate::platform::chip::Chip;
26use crate::platform::mpu::{self, MPU};
27use crate::process::ProcessBinary;
28use crate::process::{BinaryVersion, ReturnArguments};
29use crate::process::{Error, FunctionCall, FunctionCallSource, Process, Task};
30use crate::process::{FaultAction, ProcessCustomGrantIdentifier, ProcessId};
31use crate::process::{ProcessAddresses, ProcessSizes, ShortId};
32use crate::process::{State, StoppedState};
33use crate::process_checker::AcceptedCredential;
34use crate::process_loading::ProcessLoadError;
35use crate::process_policies::ProcessFaultPolicy;
36use crate::process_policies::ProcessStandardStoragePermissionsPolicy;
37use crate::processbuffer::{ReadOnlyProcessBuffer, ReadWriteProcessBuffer};
38use crate::storage_permissions::StoragePermissions;
39use crate::syscall::{self, Syscall, SyscallReturn, UserspaceKernelBoundary};
40use crate::upcall::UpcallId;
41use crate::utilities::capability_ptr::{CapabilityPtr, CapabilityPtrPermissions};
42use crate::utilities::cells::{MapCell, NumericCellExt, OptionalCell};
43
44use tock_tbf::types::CommandPermissions;
45
46/// Gets a mutable (unique) reference to the contained value.
47///
48/// TODO: this is copied from the standard library, where it is available under
49/// the `maybe_uninit_slice` nightly feature. Remove and switch to the core
50/// library variant once that is stable.
51///
52/// # Safety
53///
54/// Calling this when the content is not yet fully initialized causes undefined
55/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the
56/// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot
57/// be used to initialize a `MaybeUninit` slice.
58#[inline(always)]
59const unsafe fn maybe_uninit_slice_assume_init_mut<T>(src: &mut [MaybeUninit<T>]) -> &mut [T] {
60    // SAFETY: similar to safety notes for `slice_get_ref`, but we have a
61    // mutable reference which is also guaranteed to be valid for writes.
62    #[allow(clippy::ref_as_ptr)]
63    unsafe {
64        &mut *(src as *mut [MaybeUninit<T>] as *mut [T])
65    }
66}
67
68/// Divides one mutable raw slice into two at an index.
69///
70/// This method implementation is copied from the standard library, where it is
71/// available with `raw_slice_split` nightly feature. TODO: switch to the
72/// standard library function once that is stable.
73///
74/// The first will contain all indices from `[0, mid)` (excluding the index
75/// `mid` itself) and the second will contain all indices from `[mid, len)`
76/// (excluding the index `len` itself).
77///
78/// # Panics
79///
80/// Panics if `mid > len`.
81///
82/// # Safety
83///
84/// `mid` must be [in-bounds] of the underlying [allocation].  Which means
85/// `self` must be dereferenceable and span a single allocation that is at least
86/// `mid * size_of::<T>()` bytes long. Not upholding these requirements is
87/// *[undefined behavior]* even if the resulting pointers are not used.
88///
89/// Since `len` being in-bounds is not a safety invariant of `*mut [T]` the
90/// safety requirements of this method are the same as for
91/// [`split_at_mut_unchecked`].  The explicit bounds check is only as useful as
92/// `len` is correct.
93///
94/// [`split_at_mut_unchecked`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.split_at_mut_unchecked
95/// [in-bounds]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.add-1
96/// [allocation]: https://doc.rust-lang.org/stable/std/ptr/index.html#allocation
97/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
98unsafe fn raw_slice_split_at_mut<T>(slice: *mut [T], mid: usize) -> (*mut [T], *mut [T]) {
99    assert!(mid <= slice.len());
100
101    let len = slice.len();
102    let ptr = slice.cast::<T>();
103
104    // SAFETY: Caller must pass a valid pointer and an index that is in-bounds.
105    let tail = unsafe { ptr.add(mid) };
106    (
107        core::ptr::slice_from_raw_parts_mut(ptr, mid),
108        core::ptr::slice_from_raw_parts_mut(tail, len - mid),
109    )
110}
111
112/// Interface supported by [`ProcessStandard`] for recording debug information.
113///
114/// This trait provides flexibility to users of [`ProcessStandard`] to determine
115/// how debugging information should be recorded, or if debugging information
116/// should be recorded at all.
117///
118/// Platforms that want to only maintain certain debugging information can
119/// implement only part of this trait.
120///
121/// Tock provides a default implementation of this trait on the `()` type.
122/// Kernels that wish to use [`ProcessStandard`] but do not need process-level
123/// debugging information can use `()` as the `ProcessStandardDebug` type.
124pub trait ProcessStandardDebug: Default {
125    /// Record the address in flash the process expects to start at.
126    fn set_fixed_address_flash(&self, address: u32);
127    /// Get the address in flash the process expects to start at, if it was
128    /// recorded.
129    fn get_fixed_address_flash(&self) -> Option<u32>;
130    /// Record the address in RAM the process expects to start at.
131    fn set_fixed_address_ram(&self, address: u32);
132    /// Get the address in RAM the process expects to start at, if it was
133    /// recorded.
134    fn get_fixed_address_ram(&self) -> Option<u32>;
135    /// Record the address where the process placed its heap.
136    fn set_app_heap_start_pointer(&self, ptr: *const u8);
137    /// Get the address where the process placed its heap, if it was recorded.
138    fn get_app_heap_start_pointer(&self) -> Option<*const u8>;
139    /// Record the address where the process placed its stack.
140    fn set_app_stack_start_pointer(&self, ptr: *const u8);
141    /// Get the address where the process placed its stack, if it was recorded.
142    fn get_app_stack_start_pointer(&self) -> Option<*const u8>;
143    /// Update the lowest address that the process's stack has reached.
144    fn set_app_stack_min_pointer(&self, ptr: *const u8);
145    /// Get the lowest address of the process's stack , if it was recorded.
146    fn get_app_stack_min_pointer(&self) -> Option<*const u8>;
147    /// Provide the current address of the bottom of the stack and record the
148    /// address if it is the lowest address that the process's stack has
149    /// reached.
150    fn set_new_app_stack_min_pointer(&self, ptr: *const u8);
151
152    /// Record the most recent system call the process called.
153    fn set_last_syscall(&self, syscall: Syscall);
154    /// Get the most recent system call the process called, if it was recorded.
155    fn get_last_syscall(&self) -> Option<Syscall>;
156    /// Clear any record of the most recent system call the process called.
157    fn reset_last_syscall(&self);
158
159    /// Increase the recorded count of the number of system calls the process
160    /// has called.
161    fn increment_syscall_count(&self);
162    /// Get the recorded count of the number of system calls the process has
163    /// called.
164    ///
165    /// This should return 0 if
166    /// [`ProcessStandardDebug::increment_syscall_count()`] is never called.
167    fn get_syscall_count(&self) -> usize;
168    /// Reset the recorded count of the number of system calls called by the app
169    /// to 0.
170    fn reset_syscall_count(&self);
171
172    /// Increase the recorded count of the number of upcalls that have been
173    /// dropped for the process.
174    fn increment_dropped_upcall_count(&self);
175    /// Get the recorded count of the number of upcalls that have been dropped
176    /// for the process.
177    ///
178    /// This should return 0 if
179    /// [`ProcessStandardDebug::increment_dropped_upcall_count()`] is never
180    /// called.
181    fn get_dropped_upcall_count(&self) -> usize;
182    /// Reset the recorded count of the number of upcalls that have been dropped
183    /// for the process to 0.
184    fn reset_dropped_upcall_count(&self);
185
186    /// Increase the recorded count of the number of times the process has
187    /// exceeded its timeslice.
188    fn increment_timeslice_expiration_count(&self);
189    /// Get the recorded count of the number times the process has exceeded its
190    /// timeslice.
191    ///
192    /// This should return 0 if
193    /// [`ProcessStandardDebug::increment_timeslice_expiration_count()`] is
194    /// never called.
195    fn get_timeslice_expiration_count(&self) -> usize;
196    /// Reset the recorded count of the number of the process has exceeded its
197    /// timeslice to 0.
198    fn reset_timeslice_expiration_count(&self);
199}
200
201/// A debugging implementation for [`ProcessStandard`] that records the full
202/// debugging state.
203pub struct ProcessStandardDebugFull {
204    /// Inner field for the debug state that is in a [`MapCell`] to provide
205    /// mutable access.
206    debug: MapCell<ProcessStandardDebugFullInner>,
207}
208
209/// Struct for debugging [`ProcessStandard`] processes that records the full set
210/// of debugging information.
211///
212/// These pointers and counters are not strictly required for kernel operation,
213/// but provide helpful information when an app crashes.
214#[derive(Default)]
215struct ProcessStandardDebugFullInner {
216    /// If this process was compiled for fixed addresses, save the address
217    /// it must be at in flash. This is useful for debugging and saves having
218    /// to re-parse the entire TBF header.
219    fixed_address_flash: Option<u32>,
220
221    /// If this process was compiled for fixed addresses, save the address
222    /// it must be at in RAM. This is useful for debugging and saves having
223    /// to re-parse the entire TBF header.
224    fixed_address_ram: Option<u32>,
225
226    /// Where the process has started its heap in RAM.
227    app_heap_start_pointer: Option<*const u8>,
228
229    /// Where the start of the stack is for the process. If the kernel does the
230    /// PIC setup for this app then we know this, otherwise we need the app to
231    /// tell us where it put its stack.
232    app_stack_start_pointer: Option<*const u8>,
233
234    /// How low have we ever seen the stack pointer.
235    app_stack_min_pointer: Option<*const u8>,
236
237    /// How many syscalls have occurred since the process started.
238    syscall_count: usize,
239
240    /// What was the most recent syscall.
241    last_syscall: Option<Syscall>,
242
243    /// How many upcalls were dropped because the queue was insufficiently
244    /// long.
245    dropped_upcall_count: usize,
246
247    /// How many times this process has been paused because it exceeded its
248    /// timeslice.
249    timeslice_expiration_count: usize,
250}
251
252impl ProcessStandardDebug for ProcessStandardDebugFull {
253    fn set_fixed_address_flash(&self, address: u32) {
254        self.debug.map(|d| d.fixed_address_flash = Some(address));
255    }
256    fn get_fixed_address_flash(&self) -> Option<u32> {
257        self.debug.map_or(None, |d| d.fixed_address_flash)
258    }
259    fn set_fixed_address_ram(&self, address: u32) {
260        self.debug.map(|d| d.fixed_address_ram = Some(address));
261    }
262    fn get_fixed_address_ram(&self) -> Option<u32> {
263        self.debug.map_or(None, |d| d.fixed_address_ram)
264    }
265    fn set_app_heap_start_pointer(&self, ptr: *const u8) {
266        self.debug.map(|d| d.app_heap_start_pointer = Some(ptr));
267    }
268    fn get_app_heap_start_pointer(&self) -> Option<*const u8> {
269        self.debug.map_or(None, |d| d.app_heap_start_pointer)
270    }
271    fn set_app_stack_start_pointer(&self, ptr: *const u8) {
272        self.debug.map(|d| d.app_stack_start_pointer = Some(ptr));
273    }
274    fn get_app_stack_start_pointer(&self) -> Option<*const u8> {
275        self.debug.map_or(None, |d| d.app_stack_start_pointer)
276    }
277    fn set_app_stack_min_pointer(&self, ptr: *const u8) {
278        self.debug.map(|d| d.app_stack_min_pointer = Some(ptr));
279    }
280    fn get_app_stack_min_pointer(&self) -> Option<*const u8> {
281        self.debug.map_or(None, |d| d.app_stack_min_pointer)
282    }
283    fn set_new_app_stack_min_pointer(&self, ptr: *const u8) {
284        self.debug.map(|d| {
285            match d.app_stack_min_pointer {
286                None => d.app_stack_min_pointer = Some(ptr),
287                Some(asmp) => {
288                    // Update max stack depth if needed.
289                    if ptr < asmp {
290                        d.app_stack_min_pointer = Some(ptr);
291                    }
292                }
293            }
294        });
295    }
296
297    fn set_last_syscall(&self, syscall: Syscall) {
298        self.debug.map(|d| d.last_syscall = Some(syscall));
299    }
300    fn get_last_syscall(&self) -> Option<Syscall> {
301        self.debug.map_or(None, |d| d.last_syscall)
302    }
303    fn reset_last_syscall(&self) {
304        self.debug.map(|d| d.last_syscall = None);
305    }
306
307    fn increment_syscall_count(&self) {
308        self.debug.map(|d| d.syscall_count += 1);
309    }
310    fn get_syscall_count(&self) -> usize {
311        self.debug.map_or(0, |d| d.syscall_count)
312    }
313    fn reset_syscall_count(&self) {
314        self.debug.map(|d| d.syscall_count = 0);
315    }
316
317    fn increment_dropped_upcall_count(&self) {
318        self.debug.map(|d| d.dropped_upcall_count += 1);
319    }
320    fn get_dropped_upcall_count(&self) -> usize {
321        self.debug.map_or(0, |d| d.dropped_upcall_count)
322    }
323    fn reset_dropped_upcall_count(&self) {
324        self.debug.map(|d| d.dropped_upcall_count = 0);
325    }
326
327    fn increment_timeslice_expiration_count(&self) {
328        self.debug.map(|d| d.timeslice_expiration_count += 1);
329    }
330    fn get_timeslice_expiration_count(&self) -> usize {
331        self.debug.map_or(0, |d| d.timeslice_expiration_count)
332    }
333    fn reset_timeslice_expiration_count(&self) {
334        self.debug.map(|d| d.timeslice_expiration_count = 0);
335    }
336}
337
338impl Default for ProcessStandardDebugFull {
339    fn default() -> Self {
340        Self {
341            debug: MapCell::new(ProcessStandardDebugFullInner::default()),
342        }
343    }
344}
345
346impl ProcessStandardDebug for () {
347    fn set_fixed_address_flash(&self, _address: u32) {}
348    fn get_fixed_address_flash(&self) -> Option<u32> {
349        None
350    }
351    fn set_fixed_address_ram(&self, _address: u32) {}
352    fn get_fixed_address_ram(&self) -> Option<u32> {
353        None
354    }
355    fn set_app_heap_start_pointer(&self, _ptr: *const u8) {}
356    fn get_app_heap_start_pointer(&self) -> Option<*const u8> {
357        None
358    }
359    fn set_app_stack_start_pointer(&self, _ptr: *const u8) {}
360    fn get_app_stack_start_pointer(&self) -> Option<*const u8> {
361        None
362    }
363    fn set_app_stack_min_pointer(&self, _ptr: *const u8) {}
364    fn get_app_stack_min_pointer(&self) -> Option<*const u8> {
365        None
366    }
367    fn set_new_app_stack_min_pointer(&self, _ptr: *const u8) {}
368
369    fn set_last_syscall(&self, _syscall: Syscall) {}
370    fn get_last_syscall(&self) -> Option<Syscall> {
371        None
372    }
373    fn reset_last_syscall(&self) {}
374
375    fn increment_syscall_count(&self) {}
376    fn get_syscall_count(&self) -> usize {
377        0
378    }
379    fn reset_syscall_count(&self) {}
380    fn increment_dropped_upcall_count(&self) {}
381    fn get_dropped_upcall_count(&self) -> usize {
382        0
383    }
384    fn reset_dropped_upcall_count(&self) {}
385    fn increment_timeslice_expiration_count(&self) {}
386    fn get_timeslice_expiration_count(&self) -> usize {
387        0
388    }
389    fn reset_timeslice_expiration_count(&self) {}
390}
391
392/// Entry that is stored in the grant pointer table at the top of process
393/// memory.
394///
395/// One copy of this entry struct is stored per grant region defined in the
396/// kernel. This type allows the core kernel to lookup a grant based on the
397/// driver_num associated with the grant, and also holds the pointer to the
398/// memory allocated for the particular grant.
399#[repr(C)]
400struct GrantPointerEntry {
401    /// The syscall driver number associated with the allocated grant.
402    ///
403    /// This defaults to 0 if the grant has not been allocated. Note, however,
404    /// that 0 is a valid driver_num, and therefore cannot be used to check if a
405    /// grant is allocated or not.
406    driver_num: usize,
407
408    /// The start of the memory location where the grant has been allocated, or
409    /// null if the grant has not been allocated.
410    grant_ptr: *mut u8,
411}
412
413/// A type for userspace processes in Tock.
414///
415/// As its name implies, this is the standard implementation for Tock processes
416/// that exposes the full support for processes running on embedded hardware.
417///
418/// [`ProcessStandard`] is templated on two parameters:
419///
420/// - `C`: [`Chip`]: The implementation must know the [`Chip`] the kernel is
421///   running on to properly store architecture-specific and MPU state for the
422///   process.
423/// - `D`: [`ProcessStandardDebug`]: This configures the debugging mechanism the
424///   process uses for storing optional debugging data. Kernels that do not wish
425///   to store per-process debugging state can use the `()` type for this
426///   parameter.
427pub struct ProcessStandard<'a, C: 'static + Chip, D: 'static + ProcessStandardDebug + Default> {
428    /// Identifier of this process and the index of the process in the process
429    /// table.
430    process_id: Cell<ProcessId>,
431
432    /// An application ShortId, generated from process loading and
433    /// checking, which denotes the security identity of this process.
434    app_id: ShortId,
435
436    /// Pointer to the main Kernel struct.
437    kernel: &'static Kernel,
438
439    /// Pointer to the struct that defines the actual chip the kernel is running
440    /// on. This is used because processes have subtle hardware-based
441    /// differences. Specifically, the actual syscall interface and how
442    /// processes are switched to is architecture-specific, and how memory must
443    /// be allocated for memory protection units is also hardware-specific.
444    chip: &'static C,
445
446    /// Application memory layout:
447    ///
448    /// ```text
449    ///     ╒════════ ← memory_start + memory_len
450    ///  ╔═ │ Grant Pointers
451    ///  ║  │ ──────
452    ///  ║  │ Upcall Queue
453    ///  ║  │ ──────
454    ///     │ Process Control Block
455    ///  D  │ ──────
456    ///  Y  │ Grant Regions
457    ///  N  │
458    ///  A  │   ↓
459    ///  M  │ ──────  ← kernel_memory_break
460    ///  I  │
461    ///  C  │ ──────  ← app_break               ═╗
462    ///     │                                    ║
463    ///  ║  │   ↑                                  A
464    ///  ║  │  Heap                              P C
465    ///  ╠═ │ ──────  ← app_heap_start           R C
466    ///     │  Data                              O E
467    ///  F  │ ──────  ← data_start_pointer       C S
468    ///  I  │ Stack                              E S
469    ///  X  │   ↓                                S I
470    ///  E  │                                    S B
471    ///  D  │ ──────  ← current_stack_pointer      L
472    ///     │                                    ║ E
473    ///  ╚═ ╘════════ ← memory_start            ═╝
474    /// ```
475    ///
476    /// The start of process memory. We store this as a pointer and length and
477    /// not a slice due to Rust aliasing rules. If we were to store a slice,
478    /// then any time another slice to the same memory or an ProcessBuffer is
479    /// used in the kernel would be undefined behavior.
480    memory_start: *const u8,
481    /// Number of bytes of memory allocated to this process.
482    memory_len: usize,
483
484    /// Reference to the slice of `GrantPointerEntry`s stored in the process's
485    /// memory reserved for the kernel. These driver numbers are zero and
486    /// pointers are null if the grant region has not been allocated. When the
487    /// grant region is allocated these pointers are updated to point to the
488    /// allocated memory and the driver number is set to match the driver that
489    /// owns the grant. No other reference to these pointers exists in the Tock
490    /// kernel.
491    grant_pointers: MapCell<&'static mut [GrantPointerEntry]>,
492
493    /// Pointer to the end of the allocated (and MPU protected) grant region.
494    kernel_memory_break: Cell<*const u8>,
495
496    /// Pointer to the end of process RAM that has been sbrk'd to the process.
497    app_break: Cell<*const u8>,
498
499    /// Pointer to high water mark for process buffers shared through `allow`
500    allow_high_water_mark: Cell<*const u8>,
501
502    /// Process flash segment. This is the region of nonvolatile flash that
503    /// the process occupies.
504    flash: &'static [u8],
505
506    /// The footers of the process binary (may be zero-sized), which are metadata
507    /// about the process not covered by integrity. Used, among other things, to
508    /// store signatures.
509    footers: &'static [u8],
510
511    /// Collection of pointers to the TBF header in flash.
512    header: tock_tbf::types::TbfHeader<'static>,
513
514    /// Credential that was approved for this process, or `None` if the
515    /// credential was permitted to run without an accepted credential.
516    credential: Option<AcceptedCredential>,
517
518    /// State saved on behalf of the process each time the app switches to the
519    /// kernel.
520    stored_state:
521        MapCell<<<C as Chip>::UserspaceKernelBoundary as UserspaceKernelBoundary>::StoredState>,
522
523    /// The current state of the app. The scheduler uses this to determine
524    /// whether it can schedule this app to execute.
525    ///
526    /// The `state` is used both for bookkeeping for the scheduler as well as
527    /// for enabling control by other parts of the system. The scheduler keeps
528    /// track of if a process is ready to run or not by switching between the
529    /// `Running` and `Yielded` states. The system can control the process by
530    /// switching it to a "stopped" state to prevent the scheduler from
531    /// scheduling it.
532    state: Cell<State>,
533
534    /// How to respond if this process faults.
535    fault_policy: &'a dyn ProcessFaultPolicy,
536
537    /// Storage permissions for this process.
538    ///
539    /// This is stored in a `Cell` because we need to create the
540    /// [`ProcessStandard`] first to then later determine the storage
541    /// permissions.
542    storage_permissions: Cell<StoragePermissions>,
543
544    /// Configuration data for the MPU
545    mpu_config: MapCell<<<C as Chip>::MPU as MPU>::MpuConfig>,
546
547    /// MPU regions are saved as a pointer-size pair.
548    mpu_regions: [Cell<Option<mpu::Region>>; 6],
549
550    /// Essentially a list of upcalls that want to call functions in the
551    /// process.
552    tasks: MapCell<RingBuffer<'a, Task>>,
553
554    /// Count of how many times this process has entered the fault condition and
555    /// been restarted. This is used by some `ProcessRestartPolicy`s to
556    /// determine if the process should be restarted or not.
557    restart_count: Cell<usize>,
558
559    /// The completion code set by the process when it last exited, restarted,
560    /// or was terminated. If the process is has never terminated, then the
561    /// `OptionalCell` will be empty (i.e. `None`). If the process has exited,
562    /// restarted, or terminated, the `OptionalCell` will contain an optional 32
563    /// bit value. The option will be `None` if the process crashed or was
564    /// stopped by the kernel and there is no provided completion code. If the
565    /// process called the exit syscall then the provided completion code will
566    /// be stored as `Some(completion code)`.
567    completion_code: OptionalCell<Option<u32>>,
568
569    /// Flag that stores whether this process has a task that is ready when
570    /// the process is in the [`State::YieldedFor`] state.
571    is_yield_wait_for_ready: Cell<bool>,
572
573    /// Values kept so that we can print useful debug messages when apps fault.
574    debug: D,
575}
576
577impl<C: Chip, D: 'static + ProcessStandardDebug> Process for ProcessStandard<'_, C, D> {
578    fn processid(&self) -> ProcessId {
579        self.process_id.get()
580    }
581
582    fn short_app_id(&self) -> ShortId {
583        self.app_id
584    }
585
586    fn binary_version(&self) -> Option<BinaryVersion> {
587        let version = self.header.get_binary_version();
588        match NonZeroU32::new(version) {
589            Some(version_nonzero) => Some(BinaryVersion::new(version_nonzero)),
590            None => None,
591        }
592    }
593
594    fn get_credential(&self) -> Option<AcceptedCredential> {
595        self.credential
596    }
597
598    fn enqueue_task(&self, task: Task) -> Result<(), ErrorCode> {
599        // If this app is in a `Fault` state then we shouldn't schedule
600        // any work for it.
601        if !self.is_running() {
602            return Err(ErrorCode::NODEVICE);
603        }
604
605        let ret = self.tasks.map_or(Err(ErrorCode::FAIL), |tasks| {
606            match tasks.enqueue(task) {
607                true => {
608                    // If the process is yielded-for this task, set the ready flag.
609                    if let State::YieldedFor(yielded_upcall_id) = self.state.get() {
610                        if let Some(upcall_id) = match task {
611                            Task::FunctionCall(FunctionCall {
612                                source: FunctionCallSource::Driver(upcall_id),
613                                ..
614                            }) => Some(upcall_id),
615                            Task::ReturnValue(ReturnArguments { upcall_id, .. }) => Some(upcall_id),
616                            _ => None,
617                        } {
618                            self.is_yield_wait_for_ready
619                                .set(upcall_id == yielded_upcall_id);
620                        }
621                    }
622                    // The task has been successfully enqueued.
623                    Ok(())
624                }
625                false => {
626                    // The task could not be enqueued as there is
627                    // insufficient space in the ring buffer.
628                    Err(ErrorCode::NOMEM)
629                }
630            }
631        });
632
633        if ret.is_err() {
634            // On any error we were unable to enqueue the task. Record the
635            // error, but importantly do _not_ increment kernel work.
636            self.debug.increment_dropped_upcall_count();
637        }
638
639        ret
640    }
641
642    fn ready(&self) -> bool {
643        match self.state.get() {
644            State::Running => true,
645            State::YieldedFor(_) => self.is_yield_wait_for_ready.get(),
646            State::Yielded => self.tasks.map_or(false, |ring_buf| ring_buf.has_elements()),
647            _ => false,
648        }
649    }
650
651    fn remove_pending_upcalls(&self, upcall_id: UpcallId) -> usize {
652        self.tasks.map_or(0, |tasks| {
653            let count_before = tasks.len();
654            tasks.retain(|task| match task {
655                // Remove only tasks that are function calls with an id equal
656                // to `upcall_id`.
657                Task::FunctionCall(function_call) => match function_call.source {
658                    FunctionCallSource::Kernel => true,
659                    FunctionCallSource::Driver(id) => id != upcall_id,
660                },
661                _ => true,
662            });
663            let count_after = tasks.len();
664            if config::CONFIG.trace_syscalls {
665                debug!(
666                    "[{:?}] remove_pending_upcalls[{:#x}:{}] = {} upcall(s) removed",
667                    self.processid(),
668                    upcall_id.driver_num,
669                    upcall_id.subscribe_num,
670                    count_before - count_after,
671                );
672            }
673            count_before - count_after
674        })
675    }
676
677    fn is_running(&self) -> bool {
678        match self.state.get() {
679            State::Running | State::Yielded | State::YieldedFor(_) | State::Stopped(_) => true,
680            _ => false,
681        }
682    }
683
684    fn get_state(&self) -> State {
685        self.state.get()
686    }
687
688    fn set_yielded_state(&self) {
689        if self.state.get() == State::Running {
690            self.state.set(State::Yielded);
691        }
692    }
693
694    fn set_yielded_for_state(&self, upcall_id: UpcallId) {
695        if self.state.get() == State::Running {
696            self.state.set(State::YieldedFor(upcall_id));
697
698            // Verify if the process has a task that this yield waits for
699            self.is_yield_wait_for_ready
700                .set(self.tasks.map_or(false, |tasks| {
701                    tasks
702                        .find_first_matching(|task| match task {
703                            Task::ReturnValue(ReturnArguments { upcall_id: id, .. }) => {
704                                upcall_id == *id
705                            }
706                            Task::FunctionCall(FunctionCall {
707                                source: FunctionCallSource::Driver(id),
708                                ..
709                            }) => upcall_id == *id,
710                            _ => false,
711                        })
712                        .is_some()
713                }));
714        }
715    }
716
717    fn stop(&self) {
718        match self.state.get() {
719            State::Running => self.state.set(State::Stopped(StoppedState::Running)),
720            State::Yielded => self.state.set(State::Stopped(StoppedState::Yielded)),
721            State::YieldedFor(upcall_id) => self
722                .state
723                .set(State::Stopped(StoppedState::YieldedFor(upcall_id))),
724            State::Stopped(_stopped_state) => {
725                // Already stopped, nothing to do.
726            }
727            State::Faulted | State::Terminated => {
728                // Stop has no meaning on a inactive process.
729            }
730        }
731    }
732
733    fn resume(&self) {
734        if let State::Stopped(stopped_state) = self.state.get() {
735            match stopped_state {
736                StoppedState::Running => self.state.set(State::Running),
737                StoppedState::Yielded => self.state.set(State::Yielded),
738                StoppedState::YieldedFor(upcall_id) => self.set_yielded_for_state(upcall_id),
739            }
740        }
741    }
742
743    fn set_fault_state(&self) {
744        // Use the per-process fault policy to determine what action the kernel
745        // should take since the process faulted.
746        let action = self.fault_policy.action(self);
747        match action {
748            FaultAction::Panic => {
749                // process faulted. Panic and print status
750                self.state.set(State::Faulted);
751                panic!("Process {} had a fault", self.get_process_name());
752            }
753            FaultAction::Restart => {
754                self.try_restart(None);
755            }
756            FaultAction::Stop => {
757                // This looks a lot like restart, except we just leave the app
758                // how it faulted and mark it as `Faulted`. By clearing
759                // all of the app's todo work it will not be scheduled, and
760                // clearing all of the grant regions will cause capsules to drop
761                // this app as well.
762                self.terminate(None);
763                self.state.set(State::Faulted);
764            }
765        }
766    }
767
768    fn start(&self, _cap: &dyn crate::capabilities::ProcessStartCapability) {
769        // `start()` can only be called on a terminated process.
770        if self.get_state() != State::Terminated {
771            return;
772        }
773
774        // Reset to start the process.
775        if let Ok(()) = self.reset() {
776            self.state.set(State::Yielded);
777        }
778    }
779
780    fn try_restart(&self, completion_code: Option<u32>) {
781        // `try_restart()` cannot be called if the process is terminated. Only
782        // `start()` can start a terminated process.
783        if self.get_state() == State::Terminated {
784            return;
785        }
786
787        // Terminate the process, freeing its state and removing any
788        // pending tasks from the scheduler's queue.
789        self.terminate(completion_code);
790
791        // If there is a kernel policy that controls restarts, it should be
792        // implemented here. For now, always restart.
793        if let Ok(()) = self.reset() {
794            self.state.set(State::Yielded);
795        }
796
797        // Decide what to do with res later. E.g., if we can't restart
798        // want to reclaim the process resources.
799    }
800
801    fn terminate(&self, completion_code: Option<u32>) {
802        // A process can be terminated if it is running or in the `Faulted`
803        // state. Otherwise, you cannot terminate it and this method return
804        // early.
805        //
806        // The kernel can terminate in the `Faulted` state to return the process
807        // to a state in which it can run again (e.g., reset it).
808        if !self.is_running() && self.get_state() != State::Faulted {
809            return;
810        }
811
812        // And remove those tasks
813        self.tasks.map(|tasks| {
814            tasks.empty();
815        });
816
817        // Clear any grant regions this app has setup with any capsules.
818        unsafe {
819            self.grant_ptrs_reset();
820        }
821
822        // Save the completion code.
823        self.completion_code.set(completion_code);
824
825        // Mark the app as stopped so the scheduler won't try to run it.
826        self.state.set(State::Terminated);
827    }
828
829    fn get_restart_count(&self) -> usize {
830        self.restart_count.get()
831    }
832
833    fn has_tasks(&self) -> bool {
834        self.tasks.map_or(false, |tasks| tasks.has_elements())
835    }
836
837    fn dequeue_task(&self) -> Option<Task> {
838        self.tasks.map_or(None, |tasks| tasks.dequeue())
839    }
840
841    fn remove_upcall(&self, upcall_id: UpcallId) -> Option<Task> {
842        self.tasks.map_or(None, |tasks| {
843            tasks.remove_first_matching(|task| match task {
844                Task::FunctionCall(fc) => match fc.source {
845                    FunctionCallSource::Driver(upid) => upid == upcall_id,
846                    _ => false,
847                },
848                Task::ReturnValue(rv) => rv.upcall_id == upcall_id,
849                Task::IPC(_) => false,
850            })
851        })
852    }
853
854    fn pending_tasks(&self) -> usize {
855        self.tasks.map_or(0, |tasks| tasks.len())
856    }
857
858    fn get_command_permissions(&self, driver_num: usize, offset: usize) -> CommandPermissions {
859        self.header.get_command_permissions(driver_num, offset)
860    }
861
862    fn get_storage_permissions(&self) -> StoragePermissions {
863        self.storage_permissions.get()
864    }
865
866    fn number_writeable_flash_regions(&self) -> usize {
867        self.header.number_writeable_flash_regions()
868    }
869
870    fn get_writeable_flash_region(&self, region_index: usize) -> (usize, usize) {
871        self.header.get_writeable_flash_region(region_index)
872    }
873
874    fn update_stack_start_pointer(&self, stack_pointer: *const u8) {
875        if stack_pointer >= self.mem_start() && stack_pointer < self.mem_end() {
876            self.debug.set_app_stack_start_pointer(stack_pointer);
877            // We also reset the minimum stack pointer because whatever
878            // value we had could be entirely wrong by now.
879            self.debug.set_app_stack_min_pointer(stack_pointer);
880        }
881    }
882
883    fn update_heap_start_pointer(&self, heap_pointer: *const u8) {
884        if heap_pointer >= self.mem_start() && heap_pointer < self.mem_end() {
885            self.debug.set_app_heap_start_pointer(heap_pointer);
886        }
887    }
888
889    fn setup_mpu(&self) {
890        self.mpu_config.map(|config| {
891            // # Safety
892            //
893            // `configure_mpu` is unsafe, as invoking it with an incorrect
894            // configuration can allow an untrusted application to access
895            // kernel-private memory.
896            //
897            // This call is safe given we trust that the implementation of
898            // `ProcessStandard` correctly provisions a set of MPU regions that
899            // does not grant access to any kernel-private memory, and
900            // `ProcessStandard` does not provide safe, publically accessible
901            // APIs to add other arbitrary MPU regions to this configuration.
902            unsafe {
903                self.chip.mpu().configure_mpu(config);
904            }
905        });
906    }
907
908    fn add_mpu_region(
909        &self,
910        unallocated_memory_start: *const u8,
911        unallocated_memory_size: usize,
912        min_region_size: usize,
913    ) -> Option<mpu::Region> {
914        self.mpu_config.and_then(|config| {
915            let new_region = self.chip.mpu().allocate_region(
916                unallocated_memory_start,
917                unallocated_memory_size,
918                min_region_size,
919                mpu::Permissions::ReadWriteOnly,
920                config,
921            )?;
922
923            for region in self.mpu_regions.iter() {
924                if region.get().is_none() {
925                    region.set(Some(new_region));
926                    return Some(new_region);
927                }
928            }
929
930            // Not enough room in Process struct to store the MPU region.
931            None
932        })
933    }
934
935    fn remove_mpu_region(&self, region: mpu::Region) -> Result<(), ErrorCode> {
936        self.mpu_config.map_or(Err(ErrorCode::INVAL), |config| {
937            // Find the existing mpu region that we are removing; it needs to match exactly.
938            if let Some(internal_region) = self.mpu_regions.iter().find(|r| r.get() == Some(region))
939            {
940                self.chip
941                    .mpu()
942                    .remove_memory_region(region, config)
943                    .or(Err(ErrorCode::FAIL))?;
944
945                // Remove this region from the tracking cache of mpu_regions
946                internal_region.set(None);
947                Ok(())
948            } else {
949                Err(ErrorCode::INVAL)
950            }
951        })
952    }
953
954    fn sbrk(&self, increment: isize) -> Result<CapabilityPtr, Error> {
955        // Do not modify an inactive process.
956        if !self.is_running() {
957            return Err(Error::InactiveApp);
958        }
959
960        let new_break = self.app_break.get().wrapping_offset(increment);
961        self.brk(new_break)
962    }
963
964    fn brk(&self, new_break: *const u8) -> Result<CapabilityPtr, Error> {
965        // Do not modify an inactive process.
966        if !self.is_running() {
967            return Err(Error::InactiveApp);
968        }
969
970        self.mpu_config.map_or(Err(Error::KernelError), |config| {
971            if new_break < self.allow_high_water_mark.get() || new_break >= self.mem_end() {
972                Err(Error::AddressOutOfBounds)
973            } else if new_break > self.kernel_memory_break.get() {
974                Err(Error::OutOfMemory)
975            } else if let Err(()) = self.chip.mpu().update_app_memory_region(
976                new_break,
977                self.kernel_memory_break.get(),
978                mpu::Permissions::ReadWriteOnly,
979                config,
980            ) {
981                Err(Error::OutOfMemory)
982            } else {
983                let old_break: *const u8 = self.app_break.get();
984                self.app_break.set(new_break);
985
986                // # Safety
987                //
988                // `configure_mpu` is unsafe, as invoking it with an incorrect
989                // configuration can allow an untrusted application to access
990                // kernel-private memory.
991                //
992                // This call is safe given we trust that the implementation of
993                // `ProcessStandard` correctly provisions a set of MPU regions
994                // that does not grant access to any kernel-private memory, and
995                // `ProcessStandard` does not provide safe, publically
996                // accessible APIs to add other arbitrary MPU regions to this
997                // configuration.
998                unsafe {
999                    self.chip.mpu().configure_mpu(config);
1000                }
1001
1002                if new_break > old_break {
1003                    // We need to initialize (zero) the newly accessible memory
1004                    // region at `[old_break; new_break)`. This serves two
1005                    // purposes:
1006                    //
1007                    // 1. It prevents a process from accessing any information
1008                    //    still contained in this memory from prior kernel
1009                    //    instances or processes.
1010                    //
1011                    // 2. It satisfies Rust's requirements that all
1012                    //    dereferencable memory be properly initialized. This is
1013                    //    important, as we'll be creating references into this
1014                    //    process-accessible memory region through the process
1015                    //    buffer infrastructure.
1016                    let old_break_mut_ptr: *mut u8 = old_break.cast_mut();
1017                    unsafe {
1018                        core::ptr::write_bytes(
1019                            old_break_mut_ptr,
1020                            // Set the newly app-accessible memory to `0`:
1021                            0_u8,
1022                            new_break.addr() - old_break.addr(),
1023                        );
1024                    }
1025                }
1026
1027                let base = self.mem_start() as usize;
1028                let old_break_unit_ptr: *const () = old_break.cast();
1029                // # Safety
1030                // The passed range [base, new_break) exactly matches the process' memory range,
1031                // and a process should have RW access to its own memory.
1032                let break_result = unsafe {
1033                    CapabilityPtr::new_with_authority(
1034                        old_break_unit_ptr,
1035                        base,
1036                        (new_break as usize) - base,
1037                        CapabilityPtrPermissions::ReadWrite,
1038                    )
1039                };
1040
1041                Ok(break_result)
1042            }
1043        })
1044    }
1045
1046    #[allow(clippy::not_unsafe_ptr_arg_deref)]
1047    fn build_readwrite_process_buffer(
1048        &self,
1049        buf_start_addr: *mut u8,
1050        size: usize,
1051    ) -> Result<ReadWriteProcessBuffer, ErrorCode> {
1052        if !self.is_running() {
1053            // Do not operate on an inactive process
1054            return Err(ErrorCode::FAIL);
1055        }
1056
1057        // A process is allowed to pass any pointer if the buffer length is 0,
1058        // as to revoke kernel access to a memory region without granting access
1059        // to another one
1060        if size == 0 {
1061            // Clippy complains that we're dereferencing a pointer in a public
1062            // and safe function here. While we are not dereferencing the
1063            // pointer here, we pass it along to an unsafe function, which is as
1064            // dangerous (as it is likely to be dereferenced down the line).
1065            //
1066            // Relevant discussion:
1067            // https://github.com/rust-lang/rust-clippy/issues/3045
1068            //
1069            // It should be fine to ignore the lint here, as a buffer of length
1070            // 0 will never allow dereferencing any memory in a safe manner.
1071            //
1072            // ### Safety
1073            //
1074            // We specify a zero-length buffer, so the implementation of
1075            // `ReadWriteProcessBuffer` will handle any safety issues.
1076            // Therefore, we can encapsulate the unsafe.
1077            Ok(unsafe { ReadWriteProcessBuffer::new(buf_start_addr, 0, self.processid()) })
1078        } else if self.in_app_owned_memory(buf_start_addr, size) {
1079            // TODO: Check for buffer aliasing here
1080
1081            // Valid buffer, we need to adjust the app's watermark
1082            // note: `in_app_owned_memory` ensures this offset does not wrap
1083            let buf_end_addr = buf_start_addr.wrapping_add(size);
1084            let new_water_mark = cmp::max(self.allow_high_water_mark.get(), buf_end_addr);
1085            self.allow_high_water_mark.set(new_water_mark);
1086
1087            // Clippy complains that we're dereferencing a pointer in a public
1088            // and safe function here. While we are not dereferencing the
1089            // pointer here, we pass it along to an unsafe function, which is as
1090            // dangerous (as it is likely to be dereferenced down the line).
1091            //
1092            // Relevant discussion:
1093            // https://github.com/rust-lang/rust-clippy/issues/3045
1094            //
1095            // It should be fine to ignore the lint here, as long as we make
1096            // sure that we're pointing towards userspace memory (verified using
1097            // `in_app_owned_memory`) and respect alignment and other
1098            // constraints of the Rust references created by
1099            // `ReadWriteProcessBuffer`.
1100            //
1101            // ### Safety
1102            //
1103            // We encapsulate the unsafe here on the condition in the TODO
1104            // above, as we must ensure that this `ReadWriteProcessBuffer` will
1105            // be the only reference to this memory.
1106            Ok(unsafe { ReadWriteProcessBuffer::new(buf_start_addr, size, self.processid()) })
1107        } else {
1108            Err(ErrorCode::INVAL)
1109        }
1110    }
1111
1112    #[allow(clippy::not_unsafe_ptr_arg_deref)]
1113    fn build_readonly_process_buffer(
1114        &self,
1115        buf_start_addr: *const u8,
1116        size: usize,
1117    ) -> Result<ReadOnlyProcessBuffer, ErrorCode> {
1118        if !self.is_running() {
1119            // Do not operate on an inactive process
1120            return Err(ErrorCode::FAIL);
1121        }
1122
1123        // A process is allowed to pass any pointer if the buffer length is 0,
1124        // as to revoke kernel access to a memory region without granting access
1125        // to another one
1126        if size == 0 {
1127            // Clippy complains that we're dereferencing a pointer in a public
1128            // and safe function here. While we are not dereferencing the
1129            // pointer here, we pass it along to an unsafe function, which is as
1130            // dangerous (as it is likely to be dereferenced down the line).
1131            //
1132            // Relevant discussion:
1133            // https://github.com/rust-lang/rust-clippy/issues/3045
1134            //
1135            // It should be fine to ignore the lint here, as a buffer of length
1136            // 0 will never allow dereferencing any memory in a safe manner.
1137            //
1138            // ### Safety
1139            //
1140            // We specify a zero-length buffer, so the implementation of
1141            // `ReadOnlyProcessBuffer` will handle any safety issues. Therefore,
1142            // we can encapsulate the unsafe.
1143            Ok(unsafe { ReadOnlyProcessBuffer::new(buf_start_addr, 0, self.processid()) })
1144        } else if self.in_app_owned_memory(buf_start_addr, size)
1145            || self.in_app_flash_memory(buf_start_addr, size)
1146        {
1147            // TODO: Check for buffer aliasing here
1148
1149            if self.in_app_owned_memory(buf_start_addr, size) {
1150                // Valid buffer, and since this is in read-write memory (i.e.
1151                // not flash), we need to adjust the process's watermark. Note:
1152                // `in_app_owned_memory()` ensures this offset does not wrap.
1153                let buf_end_addr = buf_start_addr.wrapping_add(size);
1154                let new_water_mark = cmp::max(self.allow_high_water_mark.get(), buf_end_addr);
1155                self.allow_high_water_mark.set(new_water_mark);
1156            }
1157
1158            // Clippy complains that we're dereferencing a pointer in a public
1159            // and safe function here. While we are not dereferencing the
1160            // pointer here, we pass it along to an unsafe function, which is as
1161            // dangerous (as it is likely to be dereferenced down the line).
1162            //
1163            // Relevant discussion:
1164            // https://github.com/rust-lang/rust-clippy/issues/3045
1165            //
1166            // It should be fine to ignore the lint here, as long as we make
1167            // sure that we're pointing towards userspace memory (verified using
1168            // `in_app_owned_memory` or `in_app_flash_memory`) and respect
1169            // alignment and other constraints of the Rust references created by
1170            // `ReadWriteProcessBuffer`.
1171            //
1172            // ### Safety
1173            //
1174            // We encapsulate the unsafe here on the condition in the TODO
1175            // above, as we must ensure that this `ReadOnlyProcessBuffer` will
1176            // be the only reference to this memory.
1177            Ok(unsafe { ReadOnlyProcessBuffer::new(buf_start_addr, size, self.processid()) })
1178        } else {
1179            Err(ErrorCode::INVAL)
1180        }
1181    }
1182
1183    unsafe fn set_byte(&self, addr: *mut u8, value: u8) -> bool {
1184        if self.in_app_owned_memory(addr, 1) {
1185            // # Safety
1186            //
1187            // We verify that this will only write process-accessible memory,
1188            // but this can still be undefined behavior if something else holds
1189            // a reference to this memory. The caller must ensure nothing else
1190            // holds a reference to this memory.
1191            unsafe {
1192                *addr = value;
1193            }
1194            true
1195        } else {
1196            false
1197        }
1198    }
1199
1200    fn grant_is_allocated(&self, grant_num: usize) -> Option<bool> {
1201        // Do not modify an inactive process.
1202        if !self.is_running() {
1203            return None;
1204        }
1205
1206        // Update the grant pointer to the address of the new allocation.
1207        self.grant_pointers.map_or(None, |grant_pointers| {
1208            // Implement `grant_pointers[grant_num]` without a chance of a
1209            // panic.
1210            grant_pointers
1211                .get(grant_num)
1212                .map(|grant_entry| !grant_entry.grant_ptr.is_null())
1213        })
1214    }
1215
1216    fn allocate_grant(
1217        &self,
1218        grant_num: usize,
1219        driver_num: usize,
1220        size: usize,
1221        align: usize,
1222    ) -> Result<(), ()> {
1223        // Do not modify an inactive process.
1224        if !self.is_running() {
1225            return Err(());
1226        }
1227
1228        // Verify the grant_num is valid.
1229        if grant_num >= self.kernel.get_grant_count_and_finalize() {
1230            return Err(());
1231        }
1232
1233        // Verify that the grant is not already allocated. If the pointer is not
1234        // null then the grant is already allocated.
1235        if let Some(is_allocated) = self.grant_is_allocated(grant_num) {
1236            if is_allocated {
1237                return Err(());
1238            }
1239        }
1240
1241        // Verify that there is not already a grant allocated with the same
1242        // `driver_num`.
1243        let exists = self.grant_pointers.map_or(false, |grant_pointers| {
1244            // Check our list of grant pointers if the driver number is used.
1245            grant_pointers.iter().any(|grant_entry| {
1246                // Check if the grant is both allocated (its grant pointer is
1247                // non null) and the driver number matches.
1248                (!grant_entry.grant_ptr.is_null()) && grant_entry.driver_num == driver_num
1249            })
1250        });
1251        // If we find a match, then the `driver_num` must already be used and
1252        // the grant allocation fails.
1253        if exists {
1254            return Err(());
1255        }
1256
1257        // Use the shared grant allocator function to actually allocate memory.
1258        // Returns `None` if the allocation cannot be created.
1259        if let Some(grant_ptr) = self.allocate_in_grant_region_internal(size, align) {
1260            // Update the grant pointer to the address of the new allocation.
1261            self.grant_pointers.map_or(Err(()), |grant_pointers| {
1262                // Implement `grant_pointers[grant_num] = grant_ptr` without a
1263                // chance of a panic.
1264                grant_pointers
1265                    .get_mut(grant_num)
1266                    .map_or(Err(()), |grant_entry| {
1267                        // Actually set the driver num and grant pointer.
1268                        grant_entry.driver_num = driver_num;
1269                        grant_entry.grant_ptr = grant_ptr.as_ptr();
1270
1271                        // If all of this worked, return true.
1272                        Ok(())
1273                    })
1274            })
1275        } else {
1276            // Could not allocate the memory for the grant region.
1277            Err(())
1278        }
1279    }
1280
1281    fn allocate_custom_grant(
1282        &self,
1283        size: usize,
1284        align: usize,
1285    ) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()> {
1286        // Do not modify an inactive process.
1287        if !self.is_running() {
1288            return Err(());
1289        }
1290
1291        // Use the shared grant allocator function to actually allocate memory.
1292        // Returns `None` if the allocation cannot be created.
1293        if let Some(ptr) = self.allocate_in_grant_region_internal(size, align) {
1294            // Create the identifier that the caller will use to get access to
1295            // this custom grant in the future.
1296            let identifier = self.create_custom_grant_identifier(ptr);
1297
1298            Ok((identifier, ptr))
1299        } else {
1300            // Could not allocate memory for the custom grant.
1301            Err(())
1302        }
1303    }
1304
1305    fn enter_grant(&self, grant_num: usize) -> Result<NonNull<u8>, Error> {
1306        // Do not try to access the grant region of an inactive process.
1307        if !self.is_running() {
1308            return Err(Error::InactiveApp);
1309        }
1310
1311        // Retrieve the grant pointer from the `grant_pointers` slice. We use
1312        // `[slice].get()` so that if the grant number is invalid this will
1313        // return `Err` and not panic.
1314        self.grant_pointers
1315            .map_or(Err(Error::KernelError), |grant_pointers| {
1316                // Implement `grant_pointers[grant_num]` without a chance of a
1317                // panic.
1318                match grant_pointers.get_mut(grant_num) {
1319                    Some(grant_entry) => {
1320                        // Get a copy of the actual grant pointer.
1321                        let grant_ptr = grant_entry.grant_ptr;
1322
1323                        // Check if the grant pointer is marked that the grant
1324                        // has already been entered. If so, return an error.
1325                        if (grant_ptr as usize) & 0x1 == 0x1 {
1326                            // Lowest bit is one, meaning this grant has been
1327                            // entered.
1328                            Err(Error::AlreadyInUse)
1329                        } else {
1330                            // Now, to mark that the grant has been entered, we
1331                            // set the lowest bit to one and save this as the
1332                            // grant pointer.
1333                            grant_entry.grant_ptr = (grant_ptr as usize | 0x1) as *mut u8;
1334
1335                            // And we return the grant pointer to the entered
1336                            // grant.
1337                            Ok(unsafe { NonNull::new_unchecked(grant_ptr) })
1338                        }
1339                    }
1340                    None => Err(Error::AddressOutOfBounds),
1341                }
1342            })
1343    }
1344
1345    fn enter_custom_grant(
1346        &self,
1347        identifier: ProcessCustomGrantIdentifier,
1348    ) -> Result<*mut u8, Error> {
1349        // Do not try to access the grant region of an inactive process.
1350        if !self.is_running() {
1351            return Err(Error::InactiveApp);
1352        }
1353
1354        // Get the address of the custom grant based on the identifier.
1355        let custom_grant_address = self.get_custom_grant_address(identifier);
1356
1357        // We never deallocate custom grants and only we can change the
1358        // `identifier` so we know this is a valid address for the custom grant.
1359        Ok(custom_grant_address as *mut u8)
1360    }
1361
1362    unsafe fn leave_grant(&self, grant_num: usize) {
1363        // Do not modify an inactive process.
1364        if !self.is_running() {
1365            return;
1366        }
1367
1368        self.grant_pointers.map(|grant_pointers| {
1369            // Implement `grant_pointers[grant_num]` without a chance of a
1370            // panic.
1371            if let Some(grant_entry) = grant_pointers.get_mut(grant_num) {
1372                // Get a copy of the actual grant pointer.
1373                let grant_ptr = grant_entry.grant_ptr;
1374
1375                // Now, to mark that the grant has been released, we set the
1376                // lowest bit back to zero and save this as the grant
1377                // pointer.
1378                grant_entry.grant_ptr = (grant_ptr as usize & !0x1) as *mut u8;
1379            }
1380        });
1381    }
1382
1383    fn grant_allocated_count(&self) -> Option<usize> {
1384        // Do not modify an inactive process.
1385        if !self.is_running() {
1386            return None;
1387        }
1388
1389        self.grant_pointers.map(|grant_pointers| {
1390            // Filter our list of grant pointers into just the non-null ones,
1391            // and count those. A grant is allocated if its grant pointer is
1392            // non-null.
1393            grant_pointers
1394                .iter()
1395                .filter(|grant_entry| !grant_entry.grant_ptr.is_null())
1396                .count()
1397        })
1398    }
1399
1400    fn lookup_grant_from_driver_num(&self, driver_num: usize) -> Result<usize, Error> {
1401        self.grant_pointers
1402            .map_or(Err(Error::KernelError), |grant_pointers| {
1403                // Filter our list of grant pointers into just the non null
1404                // ones, and count those. A grant is allocated if its grant
1405                // pointer is non-null.
1406                match grant_pointers.iter().position(|grant_entry| {
1407                    // Only consider allocated grants.
1408                    (!grant_entry.grant_ptr.is_null()) && grant_entry.driver_num == driver_num
1409                }) {
1410                    Some(idx) => Ok(idx),
1411                    None => Err(Error::OutOfMemory),
1412                }
1413            })
1414    }
1415
1416    fn is_valid_upcall_function_pointer(&self, upcall_fn: *const ()) -> bool {
1417        let ptr: *const u8 = upcall_fn.cast();
1418        let size = mem::size_of::<*const u8>();
1419
1420        // It is okay if this function is in memory or flash.
1421        self.in_app_flash_memory(ptr, size) || self.in_app_owned_memory(ptr, size)
1422    }
1423
1424    fn get_process_name(&self) -> &'static str {
1425        self.header.get_package_name().unwrap_or("")
1426    }
1427
1428    fn get_completion_code(&self) -> Option<Option<u32>> {
1429        self.completion_code.get()
1430    }
1431
1432    fn set_syscall_return_value(&self, return_value: SyscallReturn) {
1433        match self.stored_state.map(|stored_state| unsafe {
1434            // Actually set the return value for a particular process.
1435            //
1436            // The UKB implementation uses the bounds of process-accessible
1437            // memory to verify that any memory changes are valid. Here, the
1438            // unsafe promise we are making is that the bounds passed to the UKB
1439            // are correct.
1440            self.chip
1441                .userspace_kernel_boundary()
1442                .set_syscall_return_value(
1443                    self.mem_start(),
1444                    self.app_break.get(),
1445                    stored_state,
1446                    return_value,
1447                )
1448        }) {
1449            Some(Ok(())) => {
1450                // If we get an `Ok` we are all set.
1451
1452                // The process is either already in the running state (having
1453                // just called a nonblocking syscall like command) or needs to
1454                // be moved to the running state having called Yield-WaitFor and
1455                // now needing to be resumed. Either way we can set the state to
1456                // running.
1457                self.state.set(State::Running);
1458                // The task is running, if it was yielded-for an upcall,
1459                // the upcall must have been scheduled, unset
1460                // the ready flag.
1461                self.is_yield_wait_for_ready.set(false);
1462            }
1463
1464            Some(Err(())) => {
1465                // If we get an `Err`, then the UKB implementation could not set
1466                // the return value, likely because the process's stack is no
1467                // longer accessible to it. All we can do is fault.
1468                self.set_fault_state();
1469            }
1470
1471            None => {
1472                // We should never be here since `stored_state` should always be
1473                // occupied.
1474                self.set_fault_state();
1475            }
1476        }
1477    }
1478
1479    fn set_process_function(&self, callback: FunctionCall) {
1480        // See if we can actually enqueue this function for this process.
1481        // Architecture-specific code handles actually doing this since the
1482        // exact method is both architecture- and implementation-specific.
1483        //
1484        // This can fail, for example if the process does not have enough memory
1485        // remaining.
1486        match self.stored_state.map(|stored_state| {
1487            // Let the UKB implementation handle setting the process's PC so
1488            // that the process executes the upcall function. We encapsulate
1489            // unsafe here because we are guaranteeing that the memory bounds
1490            // passed to `set_process_function` are correct.
1491            unsafe {
1492                self.chip.userspace_kernel_boundary().set_process_function(
1493                    self.mem_start(),
1494                    self.app_break.get(),
1495                    stored_state,
1496                    callback,
1497                )
1498            }
1499        }) {
1500            Some(Ok(())) => {
1501                // If we got an `Ok` we are all set and should mark that this
1502                // process is ready to be scheduled.
1503
1504                // Move this process to the "running" state so the scheduler
1505                // will schedule it.
1506                self.state.set(State::Running);
1507            }
1508
1509            Some(Err(())) => {
1510                // If we got an Error, then there was likely not enough room on
1511                // the stack to allow the process to execute this function given
1512                // the details of the particular architecture this is running
1513                // on. This process has essentially faulted, so we mark it as
1514                // such.
1515                self.set_fault_state();
1516            }
1517
1518            None => {
1519                // We should never be here since `stored_state` should always be
1520                // occupied.
1521                self.set_fault_state();
1522            }
1523        }
1524    }
1525
1526    fn switch_to(&self) -> Option<syscall::ContextSwitchReason> {
1527        // Cannot switch to an invalid process
1528        if !self.is_running() {
1529            return None;
1530        }
1531
1532        let (switch_reason, stack_pointer) =
1533            self.stored_state.map_or((None, None), |stored_state| {
1534                // Switch to the process. We guarantee that the memory pointers
1535                // we pass are valid, ensuring this context switch is safe.
1536                // Therefore we encapsulate the `unsafe`.
1537                unsafe {
1538                    let (switch_reason, optional_stack_pointer) = self
1539                        .chip
1540                        .userspace_kernel_boundary()
1541                        .switch_to_process(self.mem_start(), self.app_break.get(), stored_state);
1542                    (Some(switch_reason), optional_stack_pointer)
1543                }
1544            });
1545
1546        // If the UKB implementation passed us a stack pointer, update our
1547        // debugging state. This is completely optional.
1548        if let Some(sp) = stack_pointer {
1549            self.debug.set_new_app_stack_min_pointer(sp);
1550        }
1551
1552        switch_reason
1553    }
1554
1555    fn debug_syscall_count(&self) -> usize {
1556        self.debug.get_syscall_count()
1557    }
1558
1559    fn debug_dropped_upcall_count(&self) -> usize {
1560        self.debug.get_dropped_upcall_count()
1561    }
1562
1563    fn debug_timeslice_expiration_count(&self) -> usize {
1564        self.debug.get_timeslice_expiration_count()
1565    }
1566
1567    fn debug_timeslice_expired(&self) {
1568        self.debug.increment_timeslice_expiration_count();
1569    }
1570
1571    fn debug_syscall_called(&self, last_syscall: Syscall) {
1572        self.debug.increment_syscall_count();
1573        self.debug.set_last_syscall(last_syscall);
1574    }
1575
1576    fn debug_syscall_last(&self) -> Option<Syscall> {
1577        self.debug.get_last_syscall()
1578    }
1579
1580    fn get_addresses(&self) -> ProcessAddresses {
1581        ProcessAddresses {
1582            flash_start: self.flash_start() as usize,
1583            flash_non_protected_start: self.flash_non_protected_start() as usize,
1584            flash_integrity_end: ((self.flash.as_ptr() as usize)
1585                + (self.header.get_binary_end() as usize))
1586                as *const u8,
1587            flash_end: self.flash_end() as usize,
1588            sram_start: self.mem_start() as usize,
1589            sram_app_brk: self.app_memory_break() as usize,
1590            sram_grant_start: self.kernel_memory_break() as usize,
1591            sram_end: self.mem_end() as usize,
1592            sram_heap_start: self.debug.get_app_heap_start_pointer().map(|p| p as usize),
1593            sram_stack_top: self.debug.get_app_stack_start_pointer().map(|p| p as usize),
1594            sram_stack_bottom: self.debug.get_app_stack_min_pointer().map(|p| p as usize),
1595        }
1596    }
1597
1598    fn get_sizes(&self) -> ProcessSizes {
1599        ProcessSizes {
1600            grant_pointers: mem::size_of::<GrantPointerEntry>()
1601                * self.kernel.get_grant_count_and_finalize(),
1602            upcall_list: Self::CALLBACKS_SIZE,
1603            process_control_block: Self::PROCESS_STRUCT_SIZE,
1604        }
1605    }
1606
1607    fn print_full_process(&self, writer: &mut dyn Write) {
1608        if !config::CONFIG.debug_panics {
1609            return;
1610        }
1611
1612        self.stored_state.map(|stored_state| {
1613            // We guarantee the memory bounds pointers provided to the UKB are
1614            // correct.
1615            unsafe {
1616                self.chip.userspace_kernel_boundary().print_context(
1617                    self.mem_start(),
1618                    self.app_break.get(),
1619                    stored_state,
1620                    writer,
1621                );
1622            }
1623        });
1624
1625        // Display grant information.
1626        let number_grants = self.kernel.get_grant_count_and_finalize();
1627        let _ = writer.write_fmt(format_args!(
1628            "\
1629            \r\n Total number of grant regions defined: {}\r\n",
1630            self.kernel.get_grant_count_and_finalize()
1631        ));
1632        let rows = number_grants.div_ceil(3);
1633
1634        // Access our array of grant pointers.
1635        self.grant_pointers.map(|grant_pointers| {
1636            // Iterate each grant and show its address.
1637            for i in 0..rows {
1638                for j in 0..3 {
1639                    let index = i + (rows * j);
1640                    if index >= number_grants {
1641                        break;
1642                    }
1643
1644                    // Implement `grant_pointers[grant_num]` without a chance of
1645                    // a panic.
1646                    grant_pointers.get(index).map(|grant_entry| {
1647                        if grant_entry.grant_ptr.is_null() {
1648                            let _ =
1649                                writer.write_fmt(format_args!("  Grant {:>2} : --        ", index));
1650                        } else {
1651                            let _ = writer.write_fmt(format_args!(
1652                                "  Grant {:>2} {:#x}: {:p}",
1653                                index, grant_entry.driver_num, grant_entry.grant_ptr
1654                            ));
1655                        }
1656                    });
1657                }
1658                let _ = writer.write_fmt(format_args!("\r\n"));
1659            }
1660        });
1661
1662        // Display the current state of the MPU for this process.
1663        self.mpu_config.map(|config| {
1664            let _ = writer.write_fmt(format_args!("{}", config));
1665        });
1666
1667        // Print a helpful message on how to re-compile a process to view the
1668        // listing file. If a process is PIC, then we also need to print the
1669        // actual addresses the process executed at so that the .lst file can be
1670        // generated for those addresses. If the process was already compiled
1671        // for a fixed address, then just generating a .lst file is fine.
1672
1673        if self.debug.get_fixed_address_flash().is_some() {
1674            // Fixed addresses, can just run `make lst`.
1675            let _ = writer.write_fmt(format_args!(
1676                "\
1677                    \r\nTo debug libtock-c apps, run `make lst` in the app's\
1678                    \r\nfolder and open the arch.{:#x}.{:#x}.lst file.\r\n\r\n",
1679                self.debug.get_fixed_address_flash().unwrap_or(0),
1680                self.debug.get_fixed_address_ram().unwrap_or(0)
1681            ));
1682        } else {
1683            // PIC, need to specify the addresses.
1684            let sram_start = self.mem_start() as usize;
1685            let flash_start = self.flash.as_ptr() as usize;
1686            let flash_init_fn = flash_start + self.header.get_init_function_offset() as usize;
1687
1688            let _ = writer.write_fmt(format_args!(
1689                "\
1690                    \r\nTo debug libtock-c apps, run\
1691                    \r\n`make debug RAM_START={:#x} FLASH_INIT={:#x}`\
1692                    \r\nin the app's folder and open the .lst file.\r\n\r\n",
1693                sram_start, flash_init_fn
1694            ));
1695        }
1696    }
1697
1698    fn get_stored_state(&self, out: &mut [u8]) -> Result<usize, ErrorCode> {
1699        self.stored_state
1700            .map(|stored_state| {
1701                self.chip
1702                    .userspace_kernel_boundary()
1703                    .store_context(stored_state, out)
1704            })
1705            .unwrap_or(Err(ErrorCode::FAIL))
1706    }
1707}
1708
1709impl<C: 'static + Chip, D: 'static + ProcessStandardDebug> ProcessStandard<'_, C, D> {
1710    /// Alignment requirement for each `GrantPointerEntry` in the grant pointers
1711    /// slice.
1712    const GRANT_POINTERS_ALIGNMENT: usize = mem::align_of::<GrantPointerEntry>();
1713
1714    /// Number of upcalls stored in the upcall ring buffer (10 element length).
1715    const CALLBACK_LEN: usize = 10;
1716    /// Size of the upcall storage buffer.
1717    ///
1718    /// As of June 2026, we cannot do
1719    ///
1720    /// ```ignore
1721    /// const CALLBACKS_SIZE usize = mem::size_of::<MaybeUninit<[Task; Self::CALLBACK_LEN]>>();
1722    /// ```
1723    ///
1724    /// because of the error:
1725    ///
1726    /// ```ignore
1727    /// error: generic `Self` types are currently not permitted in anonymous constants
1728    ///     --> kernel/src/process_standard.rs:1712:70
1729    ///      |
1730    /// 1712 |     const CALLBACKS_SIZE: usize = mem::size_of::<MaybeUninit<[Task; Self::CALLBACK_LEN]>>();
1731    ///      |                                                                      ^^^^
1732    ///      |
1733    /// ```
1734    const CALLBACKS_SIZE: usize = mem::size_of::<Task>() * Self::CALLBACK_LEN;
1735    /// Alignment requirement of the upcall storage buffer.
1736    const CALLBACKS_ALIGNMENT: usize = mem::align_of::<Task>();
1737
1738    // Memory offset to make room for this process's control block.
1739    const PROCESS_STRUCT_SIZE: usize = mem::size_of::<ProcessStandard<C, D>>();
1740    /// Alignment requirement for `ProcessStandard`.
1741    const PROCESS_STRUCT_ALIGNMENT: usize = mem::align_of::<ProcessStandard<C, D>>();
1742
1743    /// Create a `ProcessStandard` object based on the found `ProcessBinary`.
1744    pub(crate) unsafe fn create(
1745        kernel: &'static Kernel,
1746        chip: &'static C,
1747        pb: ProcessBinary,
1748        remaining_memory: *mut [u8],
1749        fault_policy: &'static dyn ProcessFaultPolicy,
1750        storage_permissions_policy: &'static dyn ProcessStandardStoragePermissionsPolicy<C, D>,
1751        app_id: ShortId,
1752        index: usize,
1753    ) -> Result<(Option<&'static dyn Process>, *mut [u8]), (ProcessLoadError, *mut [u8])> {
1754        let process_name = pb.header.get_package_name();
1755        let process_ram_requested_size = pb.header.get_minimum_app_ram_size() as usize;
1756
1757        // Initialize MPU region configuration.
1758        let mut mpu_config = match chip.mpu().new_config() {
1759            Some(mpu_config) => mpu_config,
1760            None => return Err((ProcessLoadError::MpuConfigurationError, remaining_memory)),
1761        };
1762
1763        // Allocate MPU region for flash.
1764        if chip
1765            .mpu()
1766            .allocate_region(
1767                pb.flash.as_ptr(),
1768                pb.flash.len(),
1769                pb.flash.len(),
1770                mpu::Permissions::ReadExecuteOnly,
1771                &mut mpu_config,
1772            )
1773            .is_none()
1774        {
1775            if config::CONFIG.debug_load_processes {
1776                debug!(
1777                    "[!] flash={:#010X}-{:#010X} process={:?} - couldn't allocate MPU region for flash",
1778                    pb.flash.as_ptr() as usize,
1779                    pb.flash.as_ptr() as usize + pb.flash.len() - 1,
1780                    process_name
1781                );
1782            }
1783            return Err((ProcessLoadError::MpuInvalidFlashLength, remaining_memory));
1784        }
1785
1786        // Determine how much space we need in the application's memory space
1787        // just for kernel and grant state. We need to make sure we allocate
1788        // enough memory just for that.
1789
1790        // Calculate how many bytes we need for grant pointers.
1791        let grant_ptr_size = mem::size_of::<GrantPointerEntry>();
1792        let grant_ptrs_num = kernel.get_grant_count_and_finalize();
1793        let grant_ptrs_size = grant_ptrs_num * grant_ptr_size;
1794
1795        // Initial size of the kernel-owned part of process memory can be
1796        // calculated directly based on the initial size of all kernel-owned
1797        // data structures.
1798        //
1799        // Add the alignment size of each data structure to handle the case
1800        // where the memory region starts at the worst possible address and we
1801        // need to add padding. Note: the maximum shift will only ever be one
1802        // less than the alignment size, but to avoid unusual addresses we just
1803        // use the full alignment.
1804        let initial_kernel_memory_size = grant_ptrs_size
1805            + Self::GRANT_POINTERS_ALIGNMENT
1806            + Self::CALLBACKS_SIZE
1807            + Self::CALLBACKS_ALIGNMENT
1808            + Self::PROCESS_STRUCT_SIZE
1809            + Self::PROCESS_STRUCT_ALIGNMENT;
1810
1811        // By default we start with the initial size of process-accessible
1812        // memory set to 0. This maximizes the flexibility that processes have
1813        // to allocate their memory as they see fit. If a process needs more
1814        // accessible memory it must use the `brk` memop syscalls to request
1815        // more memory.
1816        //
1817        // We must take into account any process-accessible memory required by
1818        // the context switching implementation and allocate at least that much
1819        // memory so that we can successfully switch to the process. This is
1820        // architecture and implementation specific, so we query that now.
1821        let min_process_memory_size = chip
1822            .userspace_kernel_boundary()
1823            .initial_process_app_brk_size();
1824
1825        // We have to ensure that we at least ask the MPU for
1826        // `min_process_memory_size` so that we can be sure that `app_brk` is
1827        // not set inside the kernel-owned memory region. Now, in practice,
1828        // processes should not request 0 (or very few) bytes of memory in their
1829        // TBF header (i.e. `process_ram_requested_size` will almost always be
1830        // much larger than `min_process_memory_size`), as they are unlikely to
1831        // work with essentially no available memory. But, we still must protect
1832        // for that case.
1833        let min_process_ram_size = cmp::max(process_ram_requested_size, min_process_memory_size);
1834
1835        // Minimum memory size for the process.
1836        let min_total_memory_size = min_process_ram_size + initial_kernel_memory_size;
1837
1838        // Check if this process requires a fixed memory start address. If so,
1839        // try to adjust the memory region to work for this process.
1840        //
1841        // Right now, we only support skipping some RAM and leaving a chunk
1842        // unused so that the memory region starts where the process needs it
1843        // to.
1844        let remaining_memory = if let Some(fixed_memory_start) = pb
1845            .header
1846            .get_fixed_address_ram()
1847            .map(|addr: u32| remaining_memory.cast::<u8>().with_addr(addr as usize))
1848        {
1849            // The process does have a fixed address.
1850            if fixed_memory_start == remaining_memory.cast() {
1851                // Address already matches.
1852                remaining_memory
1853            } else if fixed_memory_start > remaining_memory.cast() {
1854                // Process wants a memory address farther in memory. Try to
1855                // advance the memory region to make the address match.
1856                let diff = fixed_memory_start.addr() - remaining_memory.addr();
1857                if diff > remaining_memory.len() {
1858                    // We ran out of memory.
1859                    let actual_address = (remaining_memory.cast::<u8>())
1860                        .wrapping_byte_add(remaining_memory.len())
1861                        .wrapping_byte_sub(1);
1862                    let expected_address = fixed_memory_start;
1863                    return Err((
1864                        ProcessLoadError::MemoryAddressMismatch {
1865                            actual_address,
1866                            expected_address,
1867                        },
1868                        remaining_memory,
1869                    ));
1870                } else {
1871                    // Change the memory range to start where the process requested it.
1872                    // Because of the if statement above we know this should work. Doing
1873                    // it more cleanly would be good but was a bit beyond my borrow ken;
1874                    // calling get_mut has a mutable borrow.-pal
1875                    //
1876                    // # Safety
1877                    //
1878                    // `diff` must be within the `remaining_memory` slice. Because we
1879                    // check that `diff` is less than the length of `remaining_memory`
1880                    // we know diff will be within  `remaining_memory`.
1881                    let (_, sliced) = unsafe { raw_slice_split_at_mut(remaining_memory, diff) };
1882                    sliced
1883                }
1884            } else {
1885                // Address is earlier in memory, nothing we can do.
1886                let actual_address = remaining_memory.cast();
1887                let expected_address = fixed_memory_start;
1888                return Err((
1889                    ProcessLoadError::MemoryAddressMismatch {
1890                        actual_address,
1891                        expected_address,
1892                    },
1893                    remaining_memory,
1894                ));
1895            }
1896        } else {
1897            remaining_memory
1898        };
1899
1900        // Determine where process memory will go and allocate an MPU region.
1901        //
1902        // `[allocation_start, allocation_size)` will cover both
1903        //
1904        // - the app-owned `min_process_memory_size`-long part of memory (at
1905        //   some offset within `remaining_memory`), as well as
1906        //
1907        // - the kernel-owned allocation growing downward starting at the end
1908        //   of this allocation, `initial_kernel_memory_size` bytes long.
1909        //
1910        let (allocation_start, allocation_size) = match chip.mpu().allocate_app_memory_region(
1911            remaining_memory.cast(),
1912            remaining_memory.len(),
1913            min_total_memory_size,
1914            min_process_memory_size,
1915            initial_kernel_memory_size,
1916            mpu::Permissions::ReadWriteOnly,
1917            &mut mpu_config,
1918        ) {
1919            Some((memory_start, memory_size)) => (memory_start, memory_size),
1920            None => {
1921                // Failed to load process. Insufficient memory.
1922                if config::CONFIG.debug_load_processes {
1923                    debug!(
1924                        "[!] flash={:#010X}-{:#010X} process={:?} - couldn't allocate memory region of size >= {:#X}",
1925                        pb.flash.as_ptr() as usize,
1926                        pb.flash.as_ptr() as usize + pb.flash.len() - 1,
1927                        process_name,
1928                        min_total_memory_size
1929                    );
1930                }
1931                return Err((ProcessLoadError::NotEnoughMemory, remaining_memory));
1932            }
1933        };
1934
1935        // Determine the offset of the app-owned part of the above memory
1936        // allocation. An MPU may not place it at the very start of
1937        // `remaining_memory` for internal alignment constraints. This can only
1938        // overflow if the MPU implementation is incorrect; a compliant
1939        // implementation must return a memory allocation within the
1940        // `remaining_memory` slice.
1941        let app_memory_start_offset = allocation_start.addr() - remaining_memory.addr();
1942
1943        // Check if the memory region is valid for the process. If a process
1944        // included a fixed address for the start of RAM in its TBF header (this
1945        // field is optional, processes that are position independent do not
1946        // need a fixed address) then we check that we used the same address
1947        // when we allocated it in RAM.
1948        if let Some(fixed_memory_start) = pb
1949            .header
1950            .get_fixed_address_ram()
1951            .map(|addr: u32| remaining_memory.cast::<u8>().with_addr(addr as usize))
1952        {
1953            let actual_address = remaining_memory
1954                .cast::<u8>()
1955                .wrapping_byte_add(app_memory_start_offset);
1956            let expected_address = fixed_memory_start;
1957            if actual_address != expected_address {
1958                return Err((
1959                    ProcessLoadError::MemoryAddressMismatch {
1960                        actual_address,
1961                        expected_address,
1962                    },
1963                    remaining_memory,
1964                ));
1965            }
1966        }
1967
1968        // With our MPU allocation, we can begin to divide up the
1969        // `remaining_memory` slice into individual regions for the process and
1970        // kernel, as follows:
1971        //
1972        //
1973        //  ┌───────────────────────────────────────────────────────────────────────────────────────
1974        //  │ remaining_memory
1975        //  └───────────────────────────────────────────────────────────────────────────────────────
1976        //  ┆                                                                        ┆
1977        //  ┌────────────────────────────────────────────────────────────────────────┬──────────────
1978        //  │ allocated_padded_memory                                                │ unused_memory
1979        //  └────────────────────────────────────────────────────────────────────────┴──────────────
1980        //      ┆                                                                    ┆
1981        //      ┌────────────────────────────────────────────────────────────────────┐
1982        //  ┆←─→│ allocated_memory                                                   │
1983        //    ↑ └────────────────────────────────────────────────────────────────────┘
1984        //    └┄┄┄app_memory_start_offset                                            ┆
1985        //      ┌─────────────────────────┬──────────────────────────────────────────┐
1986        //      │ app_accessible_memory   │ allocated_kernel_memory                  │
1987        //      └─────────────────────────┴──────────────────────────────────────────┘
1988        //      ┆←min_process_memory_size→┆←────→┆←────initial_kernel_memory_size───→┆
1989        //                                ↑  ↑   ┆                                   ┆
1990        //              initial_app_brk┄┄┄┘  ┆   ┆ ┌┄┄┄kernel_memory_break           ┆
1991        //           initially unallocated┄┄┄┘   ┆ ↓                                 ┆
1992        //                                       ┆ ┌───────┬──────────┬──────────────┐
1993        //                                       ┆↔│process│upcall_buf│grant_pointers│
1994        //                                       ┆ └───────┴──────────┴──────────────┘
1995        //                                        ↑       ↑          ↑              ↑
1996        //             possible alignment padding┄┴┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
1997        //
1998        //
1999        // First split the `remaining_memory` into two slices:
2000        //
2001        // 1. `allocated_padded_memory`: the allocated memory region, containing:
2002        //
2003        //    1. optional padding at the start of the memory region of
2004        //       `app_memory_start_offset` bytes,
2005        //    2. the app accessible memory region of `min_process_memory_size`,
2006        //    3. optional unallocated memory, and
2007        //    4. kernel-reserved memory, growing downward starting at the end of
2008        //       `allocated_memory`.
2009        //
2010        // 2. `unused_memory`: the rest of the `remaining_memory`, not assigned
2011        //    to this app.
2012        //
2013        // # Safety
2014        //
2015        // `app_memory_start_offset + allocation_size` must be within `remaining_memory`.
2016        let (allocated_padded_memory, unused_memory) = unsafe {
2017            raw_slice_split_at_mut(remaining_memory, app_memory_start_offset + allocation_size)
2018        };
2019
2020        // Now, slice off the (optional) padding at the start:
2021        //
2022        // # Safety
2023        //
2024        // `app_memory_start_offset` must be within `allocated_padded_memory`.
2025        let (_padding, allocated_memory) =
2026            unsafe { raw_slice_split_at_mut(allocated_padded_memory, app_memory_start_offset) };
2027
2028        // We continue to sub-slice the `allocated_memory` into
2029        // process-accessible and kernel-owned memory. Prior to that, store the
2030        // start and length ofthe overall allocation:
2031        let allocated_memory_start = allocated_memory.cast();
2032        let allocated_memory_len = allocated_memory.len();
2033
2034        // Slice off the process-accessible memory:
2035        //
2036        // # Safety
2037        //
2038        // `min_process_memory_size` must be within `allocated_memory`.
2039        let (app_accessible_memory, allocated_kernel_memory) =
2040            unsafe { raw_slice_split_at_mut(allocated_memory, min_process_memory_size) };
2041
2042        // Initialize (zero) the initial process-accessible memory region. This
2043        // serves two purposes:
2044        //
2045        // 1. It prevents a process from accessing any information still
2046        //    contained in this memory from prior kernel instances or processes.
2047        //
2048        // 2. It satisfies Rust's requirements that all dereferencable memory be
2049        //    properly initialized. This is important, as we'll be creating
2050        //    references into this process-accessible memory region through the
2051        //    process buffer infrastructure.
2052        let app_accessible_memory_bytes: *mut u8 = app_accessible_memory.cast();
2053        // # Safety
2054        //
2055        // `app_accessible_memory_bytes` is from a slice, and we use that
2056        // slice's length, so we know that there is enough memory and that the
2057        // pointer is aligned.
2058        unsafe {
2059            core::ptr::write_bytes(
2060                app_accessible_memory_bytes,
2061                // Set the entire app-accessible memory region to `0`:
2062                0_u8,
2063                app_accessible_memory.len(),
2064            );
2065        }
2066
2067        // Set the initial process-accessible memory.
2068        //
2069        // # Safety
2070        //
2071        // By using the slice `app_accessible_memory` and getting a pointer to
2072        // the byte after the slice, we are ensured that the memory between the
2073        // start of the allocation and the new pointer (at the end of the slice)
2074        // is valid because of the existing slice.
2075        let initial_app_brk = unsafe {
2076            app_accessible_memory
2077                .cast::<u8>()
2078                .add(app_accessible_memory.len())
2079        };
2080
2081        // Set the initial allow high water mark to the start of process memory
2082        // since no `allow` calls have been made yet.
2083        let initial_allow_high_water_mark = app_accessible_memory.cast();
2084
2085        // Set up initial grant region.
2086        //
2087        // `kernel_memory_break` is set to the end of kernel-accessible memory
2088        // and grows downward.
2089        let mut kernel_memory_break: *mut u8 = allocated_kernel_memory
2090            .cast::<u8>()
2091            .wrapping_add(allocated_kernel_memory.len());
2092
2093        ////////////////////////
2094        // Grant Region Pointers
2095        ////////////////////////
2096
2097        // Now that we know we have the space we can setup the grant pointers.
2098        //
2099        // First, move `kernel_memory_break` up to make room for the grant pointers.
2100        kernel_memory_break = kernel_memory_break.wrapping_sub(grant_ptrs_size);
2101        // Next, use the extra alignment padding we factored in to the total
2102        // calculation of `initial_kernel_memory_size` to ensure that
2103        // `kernel_memory_break` is aligned to a `GrantPointerEntry`.
2104        kernel_memory_break = kernel_memory_break
2105            .wrapping_sub(kernel_memory_break as usize % Self::GRANT_POINTERS_ALIGNMENT);
2106
2107        // Create the `GrantPointerEntry`s in the kernel region, then initialize
2108        // them.
2109        //
2110        // Where we calculated the updated kernel_memory_break is where the
2111        // `GrantPointerEntry`s start.
2112        let grant_pointers_memory_location: *mut MaybeUninit<GrantPointerEntry> =
2113            kernel_memory_break.cast();
2114        // Get a reference to the slice of `GrantPointerEntry`s.
2115        //
2116        // # Safety
2117        //
2118        // This is safe, as `grant_pointers_memory_location` is aligned to a
2119        // `GrantPointerEntry`, and we ensured there is space for
2120        // `grant_ptrs_num` of `GrantPointerEntry`s allocated.
2121        let grant_pointers_uninit: &mut [MaybeUninit<GrantPointerEntry>] =
2122            unsafe { slice::from_raw_parts_mut(grant_pointers_memory_location, grant_ptrs_num) };
2123        // Set all grant pointers to null.
2124        for grant_entry in grant_pointers_uninit.iter_mut() {
2125            grant_entry.write(GrantPointerEntry {
2126                driver_num: 0,
2127                grant_ptr: core::ptr::null_mut(),
2128            });
2129        }
2130        // # Safety
2131        //
2132        // All values in this slice have been properly initialized.
2133        let grant_pointers = unsafe { maybe_uninit_slice_assume_init_mut(grant_pointers_uninit) };
2134
2135        ////////////////////////
2136        // Upcall Queue
2137        ////////////////////////
2138
2139        // Now that we know we have the space we can setup the memory for the
2140        // upcalls.
2141        //
2142        // Move our `kernel_memory_break` up the size of the callback slice.
2143        kernel_memory_break = kernel_memory_break.wrapping_sub(Self::CALLBACKS_SIZE);
2144        // Use the space we allocated for alignment in case the pointer is not aligned.
2145        kernel_memory_break = kernel_memory_break
2146            .wrapping_sub(kernel_memory_break as usize % Self::CALLBACKS_ALIGNMENT);
2147
2148        // Set up ring buffer for upcalls to the process. The memory is uninitialized here,
2149        // so we cast to MaybeUninit<Task> which accurately represents that state.
2150        let upcall_buf: *mut core::mem::MaybeUninit<Task> = kernel_memory_break.cast();
2151
2152        // Get a reference `&mut [Task; Self:CALLBACK_LEN]`
2153        //
2154        // # Safety
2155        //
2156        // This needs to be aligned and have allocated space for
2157        // `Self::CALLBACK_LEN` instances of `Task`. We ensured there is enough
2158        // space when we allocated `allocated_kernel_memory` and we moved
2159        // kernel_memory_break up to fit the callbacks. We ensured this is
2160        // aligned by moving `kernel_memory_break` up if needed, and we
2161        // accounted for that potential increase in size when we allocated
2162        // `allocated_kernel_memory`.
2163        let upcall_buf = unsafe { slice::from_raw_parts_mut(upcall_buf, Self::CALLBACK_LEN) };
2164        // Actually setup the ring buffer.
2165        let tasks = RingBuffer::new(upcall_buf);
2166
2167        ////////////////////////
2168        // ProcessStandard
2169        ////////////////////////
2170
2171        // Last thing in the kernel region of process RAM is the process struct.
2172        //
2173        // Move `kernel_memory_break` to make room for the `ProcessStandard` struct.
2174        kernel_memory_break = kernel_memory_break.wrapping_sub(Self::PROCESS_STRUCT_SIZE);
2175        // Use the space we allocated for alignment in case the pointer is not aligned.
2176        kernel_memory_break = kernel_memory_break
2177            .wrapping_sub(kernel_memory_break as usize % Self::PROCESS_STRUCT_ALIGNMENT);
2178
2179        // Create a pointer to where the `ProcessStandard` struct will go in the
2180        // app grant region.
2181        let process_struct_memory_location: *mut MaybeUninit<ProcessStandard<'static, C, D>> =
2182            kernel_memory_break.cast();
2183        // Get a reference to the uninitialized `ProcessStandard` object.
2184        //
2185        // Note, this requires every field be explicitly initialized, as we are
2186        // just transforming a pointer into a structure. Because the
2187        // `ProcessStandard` is not initialized we mark it with `MaybeUninit`.
2188        //
2189        // # Safety
2190        //
2191        // This must have sufficient allocated space and proper alignment. When
2192        // we sized `allocated_kernel_memory` we ensured there was room for the
2193        // entire `ProcessStandard` struct. We also allocated space for
2194        // potential alignment issues, and ensured `kernel_memory_break` was
2195        // properly aligned for `ProcessStandard`.
2196        let process_uninit: &mut MaybeUninit<ProcessStandard<C, D>> =
2197            unsafe { &mut *process_struct_memory_location };
2198
2199        // Initialize ALL fields of `ProcessStandard`.
2200        //
2201        // # Safety
2202        //
2203        // These need to be valid and aligned writes. When we create the `MaybeUnint`
2204        // ProcessStandard struct we ensure there is valid memory for the object and
2205        // that it is aligned.
2206        unsafe {
2207            init_uninit_struct!(process_uninit => ProcessStandard<C, D> {
2208                process_id: Cell::new(ProcessId::new(
2209                    kernel,
2210                    kernel.create_process_identifier(),
2211                    index,
2212                )),
2213                app_id: app_id,
2214                kernel: kernel,
2215                chip: chip,
2216                allow_high_water_mark: Cell::new(initial_allow_high_water_mark),
2217                memory_start: allocated_memory_start,
2218                memory_len: allocated_memory_len,
2219                header: pb.header,
2220                kernel_memory_break: Cell::new(kernel_memory_break),
2221                app_break: Cell::new(initial_app_brk),
2222                grant_pointers: MapCell::new(grant_pointers),
2223
2224                credential: pb.credential.get(),
2225                footers: pb.footers,
2226                flash: pb.flash,
2227
2228                stored_state: MapCell::new(Default::default()),
2229                state: Cell::new(State::Yielded),
2230                fault_policy: fault_policy,
2231                restart_count: Cell::new(0),
2232                completion_code: OptionalCell::empty(),
2233
2234                storage_permissions: Cell::new(StoragePermissions::new_null()),
2235
2236                mpu_config: MapCell::new(mpu_config),
2237                mpu_regions: [
2238                    Cell::new(None),
2239                    Cell::new(None),
2240                    Cell::new(None),
2241                    Cell::new(None),
2242                    Cell::new(None),
2243                    Cell::new(None),
2244                ],
2245                tasks: MapCell::new(tasks),
2246                is_yield_wait_for_ready: Cell::new(false),
2247
2248                debug: D::default(),
2249            });
2250        }
2251
2252        // Convert the originally uninitialized `ProcessStandard` to a proper
2253        // `ProcessStandard` struct reference.
2254        //
2255        // # Safety
2256        //
2257        // All fields in `ProcessStandard` must be initialized. We guaranteed
2258        // this by using the `init_uninit_struct!()` macro, which causes a
2259        // compiler error if there is a missing field.
2260        let process = unsafe { process_uninit.assume_init_mut() };
2261
2262        // Save copies of these in case the app was compiled for fixed addresses
2263        // for later debugging.
2264        let fixed_address_flash = process.header.get_fixed_address_flash();
2265        let fixed_address_ram = process.header.get_fixed_address_ram();
2266        if let Some(fix_addr_flash) = fixed_address_flash {
2267            process.debug.set_fixed_address_flash(fix_addr_flash);
2268        }
2269        if let Some(fix_addr_ram) = fixed_address_ram {
2270            process.debug.set_fixed_address_ram(fix_addr_ram);
2271        }
2272
2273        // Handle any architecture-specific requirements for a new process.
2274        match process.stored_state.map(|stored_state| {
2275            // # Safety
2276            //
2277            // NOTE! We have to ensure that the start of process-accessible memory
2278            // (`app_memory_start`) is word-aligned. Since we currently start
2279            // process-accessible memory at the beginning of the allocated memory
2280            // region, we trust the MPU to give us a word-aligned starting address.
2281            //
2282            // TODO: https://github.com/tock/tock/issues/1739
2283            unsafe {
2284                chip.userspace_kernel_boundary().initialize_process(
2285                    app_accessible_memory.cast(),
2286                    initial_app_brk,
2287                    stored_state,
2288                )
2289            }
2290        }) {
2291            Some(Ok(())) => {}
2292            _ => {
2293                if config::CONFIG.debug_load_processes {
2294                    debug!(
2295                        "[!] flash={:#010X}-{:#010X} process={:?} - couldn't initialize process",
2296                        pb.flash.as_ptr() as usize,
2297                        pb.flash.as_ptr() as usize + pb.flash.len() - 1,
2298                        process_name
2299                    );
2300                }
2301                // Note that since remaining_memory was split by split_at_mut into
2302                // application memory and unused_memory, a failure here will leak
2303                // the application memory. Not leaking it requires being able to
2304                // reconstitute the original memory slice.
2305                return Err((ProcessLoadError::InternalError, unused_memory));
2306            }
2307        }
2308
2309        let flash_start = process.flash.as_ptr();
2310        let app_start =
2311            flash_start.wrapping_add(process.header.get_app_start_offset() as usize) as usize;
2312        let init_addr =
2313            flash_start.wrapping_add(process.header.get_init_function_offset() as usize) as usize;
2314        let fn_base = flash_start as usize;
2315        let fn_len = process.flash.len();
2316
2317        // We need to construct a capability with sufficient authority to cover
2318        // all of a user's code, with permissions to execute it. The entirety of
2319        // flash is sufficient.
2320        //
2321        // # Safety
2322        //
2323        // TODO? I don't understand the `new_with_authority()` safety block as
2324        // it doesn't define what the caller must do.
2325        let init_fn = unsafe {
2326            CapabilityPtr::new_with_authority(
2327                init_addr as *const (),
2328                fn_base,
2329                fn_len,
2330                CapabilityPtrPermissions::Execute,
2331            )
2332        };
2333
2334        process.tasks.map(|tasks| {
2335            tasks.enqueue(Task::FunctionCall(FunctionCall {
2336                source: FunctionCallSource::Kernel,
2337                pc: init_fn,
2338                argument0: app_start,
2339                argument1: process.memory_start as usize,
2340                argument2: process.memory_len,
2341                argument3: (process.app_break.get() as usize).into(),
2342            }));
2343        });
2344
2345        // Set storage permissions. Put this at the end so that `process` is
2346        // completely formed before using it to determine the storage
2347        // permissions.
2348        process
2349            .storage_permissions
2350            .set(storage_permissions_policy.get_permissions(process));
2351
2352        // Return the process object and a remaining memory for processes slice.
2353        Ok((Some(process), unused_memory))
2354    }
2355
2356    /// Reset the process, resetting all of its state and re-initializing it so
2357    /// it can start running. Assumes the process is not running but is still in
2358    /// flash and still has its memory region allocated to it.
2359    fn reset(&self) -> Result<(), ErrorCode> {
2360        // We need a new process identifier for this process since the restarted
2361        // version is in effect a new process. This is also necessary to
2362        // invalidate any stored `ProcessId`s that point to the old version of
2363        // the process. However, the process has not moved locations in the
2364        // processes array, so we copy the existing index.
2365        let old_index = self.process_id.get().index;
2366        let new_identifier = self.kernel.create_process_identifier();
2367        self.process_id
2368            .set(ProcessId::new(self.kernel, new_identifier, old_index));
2369
2370        // Reset debug information that is per-execution and not per-process.
2371        self.debug.reset_last_syscall();
2372        self.debug.reset_syscall_count();
2373        self.debug.reset_dropped_upcall_count();
2374        self.debug.reset_timeslice_expiration_count();
2375
2376        // Reset MPU region configuration.
2377        //
2378        // TODO: ideally, this would be moved into a helper function used by
2379        // both create() and reset(), but process load debugging complicates
2380        // this. We just want to create new config with only flash and memory
2381        // regions.
2382        //
2383        // We must have a previous MPU configuration stored, fault the
2384        // process if this invariant is violated. We avoid allocating
2385        // a new MPU configuration, as this may eventually exhaust the
2386        // number of available MPU configurations.
2387        let mut mpu_config = self.mpu_config.take().ok_or(ErrorCode::FAIL)?;
2388        self.chip.mpu().reset_config(&mut mpu_config);
2389
2390        // Allocate MPU region for flash.
2391        let app_mpu_flash = self.chip.mpu().allocate_region(
2392            self.flash.as_ptr(),
2393            self.flash.len(),
2394            self.flash.len(),
2395            mpu::Permissions::ReadExecuteOnly,
2396            &mut mpu_config,
2397        );
2398        if app_mpu_flash.is_none() {
2399            // We were unable to allocate an MPU region for flash. This is very
2400            // unexpected since we previously ran this process. However, we
2401            // return now and leave the process faulted and it will not be
2402            // scheduled.
2403            return Err(ErrorCode::FAIL);
2404        }
2405
2406        // RAM
2407
2408        // Re-determine the minimum amount of RAM the kernel must allocate to
2409        // the process based on the specific requirements of the syscall
2410        // implementation.
2411        let min_process_memory_size = self
2412            .chip
2413            .userspace_kernel_boundary()
2414            .initial_process_app_brk_size();
2415
2416        // Recalculate initial_kernel_memory_size as was done in create()
2417        let grant_ptr_size = mem::size_of::<GrantPointerEntry>();
2418        let grant_ptrs_num = self.kernel.get_grant_count_and_finalize();
2419        let grant_ptrs_size = grant_ptrs_num * grant_ptr_size;
2420
2421        let initial_kernel_memory_size = grant_ptrs_size
2422            + Self::GRANT_POINTERS_ALIGNMENT
2423            + Self::CALLBACKS_SIZE
2424            + Self::CALLBACKS_ALIGNMENT
2425            + Self::PROCESS_STRUCT_SIZE
2426            + Self::PROCESS_STRUCT_ALIGNMENT;
2427
2428        let app_mpu_mem = self.chip.mpu().allocate_app_memory_region(
2429            self.mem_start(),
2430            self.memory_len,
2431            self.memory_len, //we want exactly as much as we had before restart
2432            min_process_memory_size,
2433            initial_kernel_memory_size,
2434            mpu::Permissions::ReadWriteOnly,
2435            &mut mpu_config,
2436        );
2437        let (app_mpu_mem_start, app_mpu_mem_len) = match app_mpu_mem {
2438            Some((start, len)) => (start, len),
2439            None => {
2440                // We couldn't configure the MPU for the process. This shouldn't
2441                // happen since we were able to start the process before, but at
2442                // this point it is better to leave the app faulted and not
2443                // schedule it.
2444                return Err(ErrorCode::NOMEM);
2445            }
2446        };
2447
2448        // Reset memory pointers now that we know the layout of the process
2449        // memory and know that we can configure the MPU.
2450
2451        // app_brk is set based on minimum syscall size above the start of
2452        // memory.
2453        let app_brk = app_mpu_mem_start.wrapping_add(min_process_memory_size);
2454        self.app_break.set(app_brk);
2455        // kernel_brk is calculated backwards from the end of memory the size of
2456        // the initial kernel data structures.
2457        let kernel_brk = app_mpu_mem_start
2458            .wrapping_add(app_mpu_mem_len)
2459            .wrapping_sub(initial_kernel_memory_size);
2460        self.kernel_memory_break.set(kernel_brk);
2461        // High water mark for `allow`ed memory is reset to the start of the
2462        // process's memory region.
2463        self.allow_high_water_mark.set(app_mpu_mem_start);
2464
2465        // Store the adjusted MPU configuration:
2466        self.mpu_config.replace(mpu_config);
2467
2468        // Handle any architecture-specific requirements for a process when it
2469        // first starts (as it would when it is new).
2470        let ukb_init_process = self.stored_state.map_or(Err(()), |stored_state| unsafe {
2471            self.chip.userspace_kernel_boundary().initialize_process(
2472                app_mpu_mem_start,
2473                app_brk,
2474                stored_state,
2475            )
2476        });
2477        match ukb_init_process {
2478            Ok(()) => {}
2479            Err(()) => {
2480                // We couldn't initialize the architecture-specific state for
2481                // this process. This shouldn't happen since the app was able to
2482                // be started before, but at this point the app is no longer
2483                // valid. The best thing we can do now is leave the app as still
2484                // faulted and not schedule it.
2485                return Err(ErrorCode::RESERVE);
2486            }
2487        }
2488
2489        self.restart_count.increment();
2490
2491        // Mark the state as `Yielded` for the scheduler.
2492        self.state.set(State::Yielded);
2493
2494        // And queue up this app to be restarted.
2495        let flash_start = self.flash_start();
2496        let app_start =
2497            flash_start.wrapping_add(self.header.get_app_start_offset() as usize) as usize;
2498        let init_addr =
2499            flash_start.wrapping_add(self.header.get_init_function_offset() as usize) as usize;
2500
2501        // We need to construct a capability with sufficient authority to cover all of a user's
2502        // code, with permissions to execute it. The entirety of flash is sufficient.
2503
2504        let init_fn = unsafe {
2505            CapabilityPtr::new_with_authority(
2506                init_addr as *const (),
2507                flash_start as usize,
2508                (self.flash_end() as usize) - (flash_start as usize),
2509                CapabilityPtrPermissions::Execute,
2510            )
2511        };
2512
2513        self.enqueue_task(Task::FunctionCall(FunctionCall {
2514            source: FunctionCallSource::Kernel,
2515            pc: init_fn,
2516            argument0: app_start,
2517            argument1: self.memory_start as usize,
2518            argument2: self.memory_len,
2519            argument3: (self.app_break.get() as usize).into(),
2520        }))
2521    }
2522
2523    /// Checks if the buffer represented by the passed in base pointer and size
2524    /// is within the RAM bounds currently exposed to the processes (i.e. ending
2525    /// at `app_break`). If this method returns `true`, the buffer is guaranteed
2526    /// to be accessible to the process and to not overlap with the grant
2527    /// region.
2528    fn in_app_owned_memory(&self, buf_start_addr: *const u8, size: usize) -> bool {
2529        // TODO: On some platforms, CapabilityPtr has sufficient authority that we
2530        // could skip this check.
2531        // CapabilityPtr needs to make it slightly further, and we need to add
2532        // interfaces that tell us how much assurance it gives on the current
2533        // platform.
2534        let buf_end_addr = buf_start_addr.wrapping_add(size);
2535
2536        buf_end_addr >= buf_start_addr
2537            && buf_start_addr >= self.mem_start()
2538            && buf_end_addr <= self.app_break.get()
2539    }
2540
2541    /// Checks if the buffer represented by the passed in base pointer and size
2542    /// are within the readable region of an application's flash memory.  If
2543    /// this method returns true, the buffer is guaranteed to be readable to the
2544    /// process.
2545    fn in_app_flash_memory(&self, buf_start_addr: *const u8, size: usize) -> bool {
2546        // TODO: On some platforms, CapabilityPtr has sufficient authority that we
2547        // could skip this check.
2548        // CapabilityPtr needs to make it slightly further, and we need to add
2549        // interfaces that tell us how much assurance it gives on the current
2550        // platform.
2551        let buf_end_addr = buf_start_addr.wrapping_add(size);
2552
2553        buf_end_addr >= buf_start_addr
2554            && buf_start_addr >= self.flash_non_protected_start()
2555            && buf_end_addr <= self.flash_end()
2556    }
2557
2558    /// Reset all `grant_ptr`s to NULL.
2559    unsafe fn grant_ptrs_reset(&self) {
2560        self.grant_pointers.map(|grant_pointers| {
2561            for grant_entry in grant_pointers.iter_mut() {
2562                grant_entry.driver_num = 0;
2563                grant_entry.grant_ptr = ptr::null_mut();
2564            }
2565        });
2566    }
2567
2568    /// Allocate memory in a process's grant region.
2569    ///
2570    /// Ensures that the allocation is of `size` bytes and aligned to `align`
2571    /// bytes.
2572    ///
2573    /// If there is not enough memory, or the MPU cannot isolate the process
2574    /// accessible region from the new kernel memory break after doing the
2575    /// allocation, then this will return `None`.
2576    fn allocate_in_grant_region_internal(&self, size: usize, align: usize) -> Option<NonNull<u8>> {
2577        self.mpu_config.and_then(|config| {
2578            // First, compute the candidate new pointer. Note that at this point
2579            // we have not yet checked whether there is space for this
2580            // allocation or that it meets alignment requirements.
2581            let new_break_unaligned = self.kernel_memory_break.get().wrapping_sub(size);
2582
2583            // Our minimum alignment requirement is two bytes, so that the
2584            // lowest bit of the address will always be zero and we can use it
2585            // as a flag. It doesn't hurt to increase the alignment (except for
2586            // potentially a wasted byte) so we make sure `align` is at least
2587            // two.
2588            let align = cmp::max(align, 2);
2589
2590            // The alignment must be a power of two, 2^a. The expression
2591            // `!(align - 1)` then returns a mask with leading ones, followed by
2592            // `a` trailing zeros.
2593            let alignment_mask = !(align - 1);
2594            let new_break = (new_break_unaligned as usize & alignment_mask) as *const u8;
2595
2596            // Verify there is space for this allocation
2597            if new_break < self.app_break.get() {
2598                None
2599                // Verify it didn't wrap around
2600            } else if new_break > self.kernel_memory_break.get() {
2601                None
2602                // Verify this is compatible with the MPU.
2603            } else if let Err(()) = self.chip.mpu().update_app_memory_region(
2604                self.app_break.get(),
2605                new_break,
2606                mpu::Permissions::ReadWriteOnly,
2607                config,
2608            ) {
2609                None
2610            } else {
2611                // Allocation is valid.
2612
2613                // We always allocate down, so we must lower the
2614                // kernel_memory_break.
2615                self.kernel_memory_break.set(new_break);
2616
2617                // We need `grant_ptr` as a mutable pointer.
2618                let grant_ptr: *mut u8 = new_break.cast_mut();
2619
2620                // ### Safety
2621                //
2622                // Here we are guaranteeing that `grant_ptr` is not null. We can
2623                // ensure this because we just created `grant_ptr` based on the
2624                // process's allocated memory, and we know it cannot be null.
2625                unsafe { Some(NonNull::new_unchecked(grant_ptr)) }
2626            }
2627        })
2628    }
2629
2630    /// Create the identifier for a custom grant that grant.rs uses to access
2631    /// the custom grant.
2632    ///
2633    /// We create this identifier by calculating the number of bytes between
2634    /// where the custom grant starts and the end of the process memory.
2635    fn create_custom_grant_identifier(&self, ptr: NonNull<u8>) -> ProcessCustomGrantIdentifier {
2636        let custom_grant_address = ptr.as_ptr() as usize;
2637        let process_memory_end = self.mem_end() as usize;
2638
2639        ProcessCustomGrantIdentifier {
2640            offset: process_memory_end - custom_grant_address,
2641        }
2642    }
2643
2644    /// Use a `ProcessCustomGrantIdentifier` to find the address of the
2645    /// custom grant.
2646    ///
2647    /// This reverses `create_custom_grant_identifier()`.
2648    fn get_custom_grant_address(&self, identifier: ProcessCustomGrantIdentifier) -> usize {
2649        let process_memory_end = self.mem_end() as usize;
2650
2651        // Subtract the offset in the identifier from the end of the process
2652        // memory to get the address of the custom grant.
2653        process_memory_end - identifier.offset
2654    }
2655
2656    /// Return the app's read and modify storage permissions from the TBF header
2657    /// if it exists.
2658    ///
2659    /// If the header does not exist then return `None`. If the header does
2660    /// exist, this returns a 5-tuple with:
2661    ///
2662    /// - `write_allowed`: bool. If this process should have write permissions.
2663    /// - `read_count`: usize. How many read IDs are valid.
2664    /// - `read_ids`: [u32]. The read IDs.
2665    /// - `modify_count`: usze. How many modify IDs are valid.
2666    /// - `modify_ids`: [u32]. The modify IDs.
2667    pub fn get_tbf_storage_permissions(&self) -> Option<(bool, usize, [u32; 8], usize, [u32; 8])> {
2668        let read_perms = self.header.get_storage_read_ids();
2669        let modify_perms = self.header.get_storage_modify_ids();
2670
2671        match (read_perms, modify_perms) {
2672            (Some((read_count, read_ids)), Some((modify_count, modify_ids))) => Some((
2673                self.header.get_storage_write_id().is_some(),
2674                read_count,
2675                read_ids,
2676                modify_count,
2677                modify_ids,
2678            )),
2679            _ => None,
2680        }
2681    }
2682
2683    /// The start address of allocated RAM for this process.
2684    fn mem_start(&self) -> *const u8 {
2685        self.memory_start
2686    }
2687
2688    /// The first address after the end of the allocated RAM for this process.
2689    fn mem_end(&self) -> *const u8 {
2690        self.memory_start.wrapping_add(self.memory_len)
2691    }
2692
2693    /// The start address of the flash region allocated for this process.
2694    fn flash_start(&self) -> *const u8 {
2695        self.flash.as_ptr()
2696    }
2697
2698    /// Get the first address of process's flash that isn't protected by the
2699    /// kernel. The protected range of flash contains the TBF header and
2700    /// potentially other state the kernel is storing on behalf of the process,
2701    /// and cannot be edited by the process.
2702    fn flash_non_protected_start(&self) -> *const u8 {
2703        ((self.flash.as_ptr() as usize) + self.header.get_protected_size() as usize) as *const u8
2704    }
2705
2706    /// The first address after the end of the flash region allocated for this
2707    /// process.
2708    fn flash_end(&self) -> *const u8 {
2709        self.flash.as_ptr().wrapping_add(self.flash.len())
2710    }
2711
2712    /// The lowest address of the grant region for the process.
2713    fn kernel_memory_break(&self) -> *const u8 {
2714        self.kernel_memory_break.get()
2715    }
2716
2717    /// Return the highest address the process has access to, or the current
2718    /// process memory brk.
2719    fn app_memory_break(&self) -> *const u8 {
2720        self.app_break.get()
2721    }
2722}