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                    let opt_this_upcall_id = match task {
609                        Task::FunctionCall(FunctionCall {
610                            source: FunctionCallSource::Driver(upcall_id),
611                            ..
612                        }) => Some(upcall_id),
613                        Task::ReturnValue(ReturnArguments { upcall_id, .. }) => Some(upcall_id),
614                        _ => None,
615                    };
616
617                    // If the process is yielded-for this task, set the ready flag.
618                    //
619                    // In case the process is yielding for another upcall, don't
620                    // clear the flag; this would re-introduce the race
621                    // condition of #5195.
622                    if let State::YieldedFor(yielded_upcall_id) = self.state.get()
623                        && let Some(this_upcall_id) = opt_this_upcall_id
624                        && yielded_upcall_id == this_upcall_id
625                    {
626                        self.is_yield_wait_for_ready.set(true);
627                    }
628
629                    // The task has been successfully enqueued.
630                    Ok(())
631                }
632                false => {
633                    // The task could not be enqueued as there is
634                    // insufficient space in the ring buffer.
635                    Err(ErrorCode::NOMEM)
636                }
637            }
638        });
639
640        if ret.is_err() {
641            // On any error we were unable to enqueue the task. Record the
642            // error, but importantly do _not_ increment kernel work.
643            self.debug.increment_dropped_upcall_count();
644        }
645
646        ret
647    }
648
649    fn ready(&self) -> bool {
650        match self.state.get() {
651            State::Running => true,
652            State::YieldedFor(_) => self.is_yield_wait_for_ready.get(),
653            State::Yielded => self.tasks.map_or(false, |ring_buf| ring_buf.has_elements()),
654            _ => false,
655        }
656    }
657
658    fn remove_pending_upcalls(&self, upcall_id: UpcallId) -> usize {
659        self.tasks.map_or(0, |tasks| {
660            let count_before = tasks.len();
661            tasks.retain(|task| match task {
662                // Remove only tasks that are function calls with an id equal
663                // to `upcall_id`.
664                Task::FunctionCall(function_call) => match function_call.source {
665                    FunctionCallSource::Kernel => true,
666                    FunctionCallSource::Driver(id) => id != upcall_id,
667                },
668                _ => true,
669            });
670            let count_after = tasks.len();
671            if config::CONFIG.trace_syscalls {
672                debug!(
673                    "[{:?}] remove_pending_upcalls[{:#x}:{}] = {} upcall(s) removed",
674                    self.processid(),
675                    upcall_id.driver_num,
676                    upcall_id.subscribe_num,
677                    count_before - count_after,
678                );
679            }
680            count_before - count_after
681        })
682    }
683
684    fn is_running(&self) -> bool {
685        match self.state.get() {
686            State::Running | State::Yielded | State::YieldedFor(_) | State::Stopped(_) => true,
687            _ => false,
688        }
689    }
690
691    fn get_state(&self) -> State {
692        self.state.get()
693    }
694
695    fn set_yielded_state(&self) {
696        if self.state.get() == State::Running {
697            self.state.set(State::Yielded);
698        }
699    }
700
701    fn set_yielded_for_state(&self, upcall_id: UpcallId) {
702        if self.state.get() == State::Running
703            || self.state.get() == State::Stopped(StoppedState::YieldedFor(upcall_id))
704        {
705            self.state.set(State::YieldedFor(upcall_id));
706
707            // Verify if the process has a task that this yield waits for
708            self.is_yield_wait_for_ready
709                .set(self.tasks.map_or(false, |tasks| {
710                    tasks
711                        .find_first_matching(|task| match task {
712                            Task::ReturnValue(ReturnArguments { upcall_id: id, .. }) => {
713                                upcall_id == *id
714                            }
715                            Task::FunctionCall(FunctionCall {
716                                source: FunctionCallSource::Driver(id),
717                                ..
718                            }) => upcall_id == *id,
719                            _ => false,
720                        })
721                        .is_some()
722                }));
723        }
724    }
725
726    fn stop(&self) {
727        match self.state.get() {
728            State::Running => self.state.set(State::Stopped(StoppedState::Running)),
729            State::Yielded => self.state.set(State::Stopped(StoppedState::Yielded)),
730            State::YieldedFor(upcall_id) => self
731                .state
732                .set(State::Stopped(StoppedState::YieldedFor(upcall_id))),
733            State::Stopped(_stopped_state) => {
734                // Already stopped, nothing to do.
735            }
736            State::Faulted | State::Terminated => {
737                // Stop has no meaning on a inactive process.
738            }
739        }
740    }
741
742    fn resume(&self) {
743        if let State::Stopped(stopped_state) = self.state.get() {
744            match stopped_state {
745                StoppedState::Running => self.state.set(State::Running),
746                StoppedState::Yielded => self.state.set(State::Yielded),
747                StoppedState::YieldedFor(upcall_id) => self.set_yielded_for_state(upcall_id),
748            }
749        }
750    }
751
752    fn set_fault_state(&self) {
753        // Use the per-process fault policy to determine what action the kernel
754        // should take since the process faulted.
755        let action = self.fault_policy.action(self);
756        match action {
757            FaultAction::Panic => {
758                // process faulted. Panic and print status
759                self.state.set(State::Faulted);
760                panic!("Process {} had a fault", self.get_process_name());
761            }
762            FaultAction::Restart => {
763                self.try_restart(None);
764            }
765            FaultAction::Stop => {
766                // This looks a lot like restart, except we just leave the app
767                // how it faulted and mark it as `Faulted`. By clearing
768                // all of the app's todo work it will not be scheduled, and
769                // clearing all of the grant regions will cause capsules to drop
770                // this app as well.
771                self.terminate(None);
772                self.state.set(State::Faulted);
773            }
774        }
775    }
776
777    fn start(&self, _cap: &dyn crate::capabilities::ProcessStartCapability) {
778        // `start()` can only be called on a terminated process.
779        if self.get_state() != State::Terminated {
780            return;
781        }
782
783        // Reset to start the process.
784        if let Ok(()) = self.reset() {
785            self.state.set(State::Yielded);
786        }
787    }
788
789    fn try_restart(&self, completion_code: Option<u32>) {
790        // `try_restart()` cannot be called if the process is terminated. Only
791        // `start()` can start a terminated process.
792        if self.get_state() == State::Terminated {
793            return;
794        }
795
796        // Terminate the process, freeing its state and removing any
797        // pending tasks from the scheduler's queue.
798        self.terminate(completion_code);
799
800        // If there is a kernel policy that controls restarts, it should be
801        // implemented here. For now, always restart.
802        if let Ok(()) = self.reset() {
803            self.state.set(State::Yielded);
804        }
805
806        // Decide what to do with res later. E.g., if we can't restart
807        // want to reclaim the process resources.
808    }
809
810    fn terminate(&self, completion_code: Option<u32>) {
811        // A process can be terminated if it is running or in the `Faulted`
812        // state. Otherwise, you cannot terminate it and this method return
813        // early.
814        //
815        // The kernel can terminate in the `Faulted` state to return the process
816        // to a state in which it can run again (e.g., reset it).
817        if !self.is_running() && self.get_state() != State::Faulted {
818            return;
819        }
820
821        // And remove those tasks
822        self.tasks.map(|tasks| {
823            tasks.empty();
824        });
825
826        // Clear any grant regions this app has setup with any capsules by
827        // setting all `grant_ptr`s to NULL.
828        self.grant_pointers.map(|grant_pointers| {
829            for grant_entry in grant_pointers.iter_mut() {
830                grant_entry.driver_num = 0;
831                grant_entry.grant_ptr = ptr::null_mut();
832            }
833        });
834
835        // Save the completion code.
836        self.completion_code.set(completion_code);
837
838        // Mark the app as stopped so the scheduler won't try to run it.
839        self.state.set(State::Terminated);
840    }
841
842    fn get_restart_count(&self) -> usize {
843        self.restart_count.get()
844    }
845
846    fn has_tasks(&self) -> bool {
847        self.tasks.map_or(false, |tasks| tasks.has_elements())
848    }
849
850    fn dequeue_task(&self) -> Option<Task> {
851        self.tasks.map_or(None, |tasks| tasks.dequeue())
852    }
853
854    fn remove_upcall(&self, upcall_id: UpcallId) -> Option<Task> {
855        self.tasks.map_or(None, |tasks| {
856            tasks.remove_first_matching(|task| match task {
857                Task::FunctionCall(fc) => match fc.source {
858                    FunctionCallSource::Driver(upid) => upid == upcall_id,
859                    _ => false,
860                },
861                Task::ReturnValue(rv) => rv.upcall_id == upcall_id,
862                Task::IPC(_) => false,
863            })
864        })
865    }
866
867    fn pending_tasks(&self) -> usize {
868        self.tasks.map_or(0, |tasks| tasks.len())
869    }
870
871    fn get_command_permissions(&self, driver_num: usize, offset: usize) -> CommandPermissions {
872        self.header.get_command_permissions(driver_num, offset)
873    }
874
875    fn get_storage_permissions(&self) -> StoragePermissions {
876        self.storage_permissions.get()
877    }
878
879    fn number_writeable_flash_regions(&self) -> usize {
880        self.header.number_writeable_flash_regions()
881    }
882
883    fn get_writeable_flash_region(&self, region_index: usize) -> (usize, usize) {
884        self.header.get_writeable_flash_region(region_index)
885    }
886
887    fn update_stack_start_pointer(&self, stack_pointer: *const u8) {
888        if stack_pointer >= self.mem_start() && stack_pointer < self.mem_end() {
889            self.debug.set_app_stack_start_pointer(stack_pointer);
890            // We also reset the minimum stack pointer because whatever
891            // value we had could be entirely wrong by now.
892            self.debug.set_app_stack_min_pointer(stack_pointer);
893        }
894    }
895
896    fn update_heap_start_pointer(&self, heap_pointer: *const u8) {
897        if heap_pointer >= self.mem_start() && heap_pointer < self.mem_end() {
898            self.debug.set_app_heap_start_pointer(heap_pointer);
899        }
900    }
901
902    fn setup_mpu(&self) {
903        self.mpu_config.map(|config| {
904            // SAFETY: `configure_mpu` is unsafe, as invoking it with an incorrect
905            // configuration can allow an untrusted application to access
906            // kernel-private memory.
907            //
908            // This call is safe given we trust that the implementation of
909            // `ProcessStandard` correctly provisions a set of MPU regions that
910            // does not grant access to any kernel-private memory, and
911            // `ProcessStandard` does not provide safe, publicly accessible
912            // APIs to add other arbitrary MPU regions to this configuration.
913            unsafe {
914                self.chip.mpu().configure_mpu(config);
915            }
916        });
917    }
918
919    fn add_mpu_region(
920        &self,
921        unallocated_memory_start: *const u8,
922        unallocated_memory_size: usize,
923        min_region_size: usize,
924    ) -> Option<mpu::Region> {
925        self.mpu_config.and_then(|config| {
926            let new_region = self.chip.mpu().allocate_region(
927                unallocated_memory_start,
928                unallocated_memory_size,
929                min_region_size,
930                mpu::Permissions::ReadWriteOnly,
931                config,
932            )?;
933
934            for region in self.mpu_regions.iter() {
935                if region.get().is_none() {
936                    region.set(Some(new_region));
937                    return Some(new_region);
938                }
939            }
940
941            // Not enough room in Process struct to store the MPU region.
942            None
943        })
944    }
945
946    fn remove_mpu_region(&self, region: mpu::Region) -> Result<(), ErrorCode> {
947        self.mpu_config.map_or(Err(ErrorCode::INVAL), |config| {
948            // Find the existing mpu region that we are removing; it needs to match exactly.
949            if let Some(internal_region) = self.mpu_regions.iter().find(|r| r.get() == Some(region))
950            {
951                self.chip
952                    .mpu()
953                    .remove_memory_region(region, config)
954                    .or(Err(ErrorCode::FAIL))?;
955
956                // Remove this region from the tracking cache of mpu_regions
957                internal_region.set(None);
958                Ok(())
959            } else {
960                Err(ErrorCode::INVAL)
961            }
962        })
963    }
964
965    fn sbrk(&self, increment: isize) -> Result<CapabilityPtr, Error> {
966        // Do not modify an inactive process.
967        if !self.is_running() {
968            return Err(Error::InactiveApp);
969        }
970
971        let new_break = self.app_break.get().wrapping_offset(increment);
972        self.brk(new_break)
973    }
974
975    fn brk(&self, new_break: *const u8) -> Result<CapabilityPtr, Error> {
976        // Do not modify an inactive process.
977        if !self.is_running() {
978            return Err(Error::InactiveApp);
979        }
980
981        self.mpu_config.map_or(Err(Error::KernelError), |config| {
982            if new_break < self.allow_high_water_mark.get() || new_break >= self.mem_end() {
983                Err(Error::AddressOutOfBounds)
984            } else if new_break > self.kernel_memory_break.get() {
985                Err(Error::OutOfMemory)
986            } else if let Err(()) = self.chip.mpu().update_app_memory_region(
987                new_break,
988                self.kernel_memory_break.get(),
989                mpu::Permissions::ReadWriteOnly,
990                config,
991            ) {
992                Err(Error::OutOfMemory)
993            } else {
994                let old_break: *const u8 = self.app_break.get();
995                self.app_break.set(new_break);
996
997                // SAFETY: `configure_mpu` is unsafe, as invoking it with an incorrect
998                // configuration can allow an untrusted application to access
999                // kernel-private memory.
1000                //
1001                // This call is safe given we trust that the implementation of
1002                // `ProcessStandard` correctly provisions a set of MPU regions
1003                // that does not grant access to any kernel-private memory, and
1004                // `ProcessStandard` does not provide safe, publicly
1005                // accessible APIs to add other arbitrary MPU regions to this
1006                // configuration.
1007                unsafe {
1008                    self.chip.mpu().configure_mpu(config);
1009                }
1010
1011                if new_break > old_break {
1012                    // We need to initialize (zero) the newly accessible memory
1013                    // region at `[old_break; new_break)`. This serves two
1014                    // purposes:
1015                    //
1016                    // 1. It prevents a process from accessing any information
1017                    //    still contained in this memory from prior kernel
1018                    //    instances or processes.
1019                    //
1020                    // 2. It satisfies Rust's requirements that all
1021                    //    dereferencable memory be properly initialized. This is
1022                    //    important, as we'll be creating references into this
1023                    //    process-accessible memory region through the process
1024                    //    buffer infrastructure.
1025                    let old_break_mut_ptr: *mut u8 = old_break.cast_mut();
1026                    // SAFETY: We know this will write to only process-accessible memory
1027                    // that has never been used to create any kernel data structures
1028                    // because of the checks at the beginning of this function. We also
1029                    // know this is valid memory to write to because we checked the
1030                    // new_break is within process memory. Because we are using `u8`, we
1031                    // know `old_break_mut_ptr` is aligned. Since the process will have
1032                    // access to this memory we know the kernel will not try to use it
1033                    // for any data structures, avoiding any potential future memory
1034                    // initialization error.
1035                    unsafe {
1036                        core::ptr::write_bytes(
1037                            old_break_mut_ptr,
1038                            // Set the newly app-accessible memory to `0`:
1039                            0_u8,
1040                            new_break.addr() - old_break.addr(),
1041                        );
1042                    }
1043                }
1044
1045                let base = self.mem_start() as usize;
1046                let old_break_unit_ptr: *const () = old_break.cast();
1047                // SAFETY: It must be safe for this process to access the
1048                // bounds+permission expressed here while assuming no other
1049                // protection mechanism is active.
1050                //  - A process should have Read+Write access to its memory.
1051                //  - The function has established [base, new_break) as the
1052                //    (new) valid bounds for process memory.
1053                //  - We grant only Read+Write permissions.
1054                //  - We only pass this pointer to this process.
1055                let break_result = unsafe {
1056                    CapabilityPtr::new_with_authority(
1057                        old_break_unit_ptr,
1058                        base,
1059                        (new_break as usize) - base,
1060                        CapabilityPtrPermissions::ReadWrite,
1061                    )
1062                };
1063
1064                Ok(break_result)
1065            }
1066        })
1067    }
1068
1069    #[allow(clippy::not_unsafe_ptr_arg_deref)]
1070    fn build_readwrite_process_buffer(
1071        &self,
1072        buf_start_addr: *mut u8,
1073        size: usize,
1074    ) -> Result<ReadWriteProcessBuffer, ErrorCode> {
1075        if !self.is_running() {
1076            // Do not operate on an inactive process
1077            return Err(ErrorCode::FAIL);
1078        }
1079
1080        // A process is allowed to pass any pointer if the buffer length is 0,
1081        // as to revoke kernel access to a memory region without granting access
1082        // to another one
1083        if size == 0 {
1084            // Clippy complains that we're dereferencing a pointer in a public
1085            // and safe function here. While we are not dereferencing the
1086            // pointer here, we pass it along to an unsafe function, which is as
1087            // dangerous (as it is likely to be dereferenced down the line).
1088            //
1089            // Relevant discussion:
1090            // https://github.com/rust-lang/rust-clippy/issues/3045
1091            //
1092            // It should be fine to ignore the lint here, as a buffer of length
1093            // 0 will never allow dereferencing any memory in a safe manner.
1094            //
1095            // SAFETY: We specify a zero-length buffer, so the implementation of
1096            // `ReadWriteProcessBuffer` will handle any safety issues.
1097            // Therefore, we can encapsulate the unsafe.
1098            Ok(unsafe { ReadWriteProcessBuffer::new(buf_start_addr, 0, self.processid()) })
1099        } else if self.in_app_owned_memory(buf_start_addr, size) {
1100            // TODO: Check for buffer aliasing here
1101
1102            // Valid buffer, we need to adjust the app's watermark
1103            // note: `in_app_owned_memory` ensures this offset does not wrap
1104            let buf_end_addr = buf_start_addr.wrapping_add(size);
1105            let new_water_mark = cmp::max(self.allow_high_water_mark.get(), buf_end_addr);
1106            self.allow_high_water_mark.set(new_water_mark);
1107
1108            // Clippy complains that we're dereferencing a pointer in a public
1109            // and safe function here. While we are not dereferencing the
1110            // pointer here, we pass it along to an unsafe function, which is as
1111            // dangerous (as it is likely to be dereferenced down the line).
1112            //
1113            // Relevant discussion:
1114            // https://github.com/rust-lang/rust-clippy/issues/3045
1115            //
1116            // It should be fine to ignore the lint here, as long as we make
1117            // sure that we're pointing towards userspace memory (verified using
1118            // `in_app_owned_memory`) and respect alignment and other
1119            // constraints of the Rust references created by
1120            // `ReadWriteProcessBuffer`.
1121            //
1122            // SAFETY: We encapsulate the unsafe here on the condition in the TODO
1123            // above, as we must ensure that this `ReadWriteProcessBuffer` will
1124            // be the only reference to this memory.
1125            Ok(unsafe { ReadWriteProcessBuffer::new(buf_start_addr, size, self.processid()) })
1126        } else {
1127            Err(ErrorCode::INVAL)
1128        }
1129    }
1130
1131    #[allow(clippy::not_unsafe_ptr_arg_deref)]
1132    fn build_readonly_process_buffer(
1133        &self,
1134        buf_start_addr: *const u8,
1135        size: usize,
1136    ) -> Result<ReadOnlyProcessBuffer, ErrorCode> {
1137        if !self.is_running() {
1138            // Do not operate on an inactive process
1139            return Err(ErrorCode::FAIL);
1140        }
1141
1142        // A process is allowed to pass any pointer if the buffer length is 0,
1143        // as to revoke kernel access to a memory region without granting access
1144        // to another one
1145        if size == 0 {
1146            // Clippy complains that we're dereferencing a pointer in a public
1147            // and safe function here. While we are not dereferencing the
1148            // pointer here, we pass it along to an unsafe function, which is as
1149            // dangerous (as it is likely to be dereferenced down the line).
1150            //
1151            // Relevant discussion:
1152            // https://github.com/rust-lang/rust-clippy/issues/3045
1153            //
1154            // It should be fine to ignore the lint here, as a buffer of length
1155            // 0 will never allow dereferencing any memory in a safe manner.
1156            //
1157            // SAFETY: We specify a zero-length buffer, so the implementation of
1158            // `ReadOnlyProcessBuffer` will handle any safety issues. Therefore,
1159            // we can encapsulate the unsafe.
1160            Ok(unsafe { ReadOnlyProcessBuffer::new(buf_start_addr, 0, self.processid()) })
1161        } else if self.in_app_owned_memory(buf_start_addr, size)
1162            || self.in_app_flash_memory(buf_start_addr, size)
1163        {
1164            // TODO: Check for buffer aliasing here
1165
1166            if self.in_app_owned_memory(buf_start_addr, size) {
1167                // Valid buffer, and since this is in read-write memory (i.e.
1168                // not flash), we need to adjust the process's watermark. Note:
1169                // `in_app_owned_memory()` ensures this offset does not wrap.
1170                let buf_end_addr = buf_start_addr.wrapping_add(size);
1171                let new_water_mark = cmp::max(self.allow_high_water_mark.get(), buf_end_addr);
1172                self.allow_high_water_mark.set(new_water_mark);
1173            }
1174
1175            // Clippy complains that we're dereferencing a pointer in a public
1176            // and safe function here. While we are not dereferencing the
1177            // pointer here, we pass it along to an unsafe function, which is as
1178            // dangerous (as it is likely to be dereferenced down the line).
1179            //
1180            // Relevant discussion:
1181            // https://github.com/rust-lang/rust-clippy/issues/3045
1182            //
1183            // It should be fine to ignore the lint here, as long as we make
1184            // sure that we're pointing towards userspace memory (verified using
1185            // `in_app_owned_memory` or `in_app_flash_memory`) and respect
1186            // alignment and other constraints of the Rust references created by
1187            // `ReadWriteProcessBuffer`.
1188            //
1189            // SAFETY: We encapsulate the unsafe here on the condition in the TODO
1190            // above, as we must ensure that this `ReadOnlyProcessBuffer` will
1191            // be the only reference to this memory.
1192            Ok(unsafe { ReadOnlyProcessBuffer::new(buf_start_addr, size, self.processid()) })
1193        } else {
1194            Err(ErrorCode::INVAL)
1195        }
1196    }
1197
1198    unsafe fn set_byte(&self, addr: *mut u8, value: u8) -> bool {
1199        if self.in_app_owned_memory(addr, 1) {
1200            // SAFETY: We verify that this will only write process-accessible memory,
1201            // but this can still be undefined behavior if something else holds
1202            // a reference to this memory. The caller must ensure nothing else
1203            // holds a reference to this memory.
1204            unsafe {
1205                *addr = value;
1206            }
1207            true
1208        } else {
1209            false
1210        }
1211    }
1212
1213    fn grant_is_allocated(&self, grant_num: usize) -> Option<bool> {
1214        // Do not modify an inactive process.
1215        if !self.is_running() {
1216            return None;
1217        }
1218
1219        // Update the grant pointer to the address of the new allocation.
1220        self.grant_pointers.map_or(None, |grant_pointers| {
1221            // Implement `grant_pointers[grant_num]` without a chance of a
1222            // panic.
1223            grant_pointers
1224                .get(grant_num)
1225                .map(|grant_entry| !grant_entry.grant_ptr.is_null())
1226        })
1227    }
1228
1229    fn allocate_grant(
1230        &self,
1231        grant_num: usize,
1232        driver_num: usize,
1233        size: usize,
1234        align: usize,
1235    ) -> Result<(), ()> {
1236        // Do not modify an inactive process.
1237        if !self.is_running() {
1238            return Err(());
1239        }
1240
1241        // Verify the grant_num is valid.
1242        if grant_num >= self.kernel.get_grant_count_and_finalize() {
1243            return Err(());
1244        }
1245
1246        // Verify that the grant is not already allocated. If the pointer is not
1247        // null then the grant is already allocated.
1248        if let Some(is_allocated) = self.grant_is_allocated(grant_num) {
1249            if is_allocated {
1250                return Err(());
1251            }
1252        }
1253
1254        // Verify that there is not already a grant allocated with the same
1255        // `driver_num`.
1256        let exists = self.grant_pointers.map_or(false, |grant_pointers| {
1257            // Check our list of grant pointers if the driver number is used.
1258            grant_pointers.iter().any(|grant_entry| {
1259                // Check if the grant is both allocated (its grant pointer is
1260                // non null) and the driver number matches.
1261                (!grant_entry.grant_ptr.is_null()) && grant_entry.driver_num == driver_num
1262            })
1263        });
1264        // If we find a match, then the `driver_num` must already be used and
1265        // the grant allocation fails.
1266        if exists {
1267            return Err(());
1268        }
1269
1270        // Use the shared grant allocator function to actually allocate memory.
1271        // Returns `None` if the allocation cannot be created.
1272        if let Some(grant_ptr) = self.allocate_in_grant_region_internal(size, align) {
1273            // Update the grant pointer to the address of the new allocation.
1274            self.grant_pointers.map_or(Err(()), |grant_pointers| {
1275                // Implement `grant_pointers[grant_num] = grant_ptr` without a
1276                // chance of a panic.
1277                grant_pointers
1278                    .get_mut(grant_num)
1279                    .map_or(Err(()), |grant_entry| {
1280                        // Actually set the driver num and grant pointer.
1281                        grant_entry.driver_num = driver_num;
1282                        grant_entry.grant_ptr = grant_ptr.as_ptr();
1283
1284                        // If all of this worked, return true.
1285                        Ok(())
1286                    })
1287            })
1288        } else {
1289            // Could not allocate the memory for the grant region.
1290            Err(())
1291        }
1292    }
1293
1294    fn allocate_custom_grant(
1295        &self,
1296        size: usize,
1297        align: usize,
1298    ) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()> {
1299        // Do not modify an inactive process.
1300        if !self.is_running() {
1301            return Err(());
1302        }
1303
1304        // Use the shared grant allocator function to actually allocate memory.
1305        // Returns `None` if the allocation cannot be created.
1306        if let Some(ptr) = self.allocate_in_grant_region_internal(size, align) {
1307            // Create the identifier that the caller will use to get access to
1308            // this custom grant in the future.
1309            let identifier = self.create_custom_grant_identifier(ptr);
1310
1311            Ok((identifier, ptr))
1312        } else {
1313            // Could not allocate memory for the custom grant.
1314            Err(())
1315        }
1316    }
1317
1318    fn enter_grant(&self, grant_num: usize) -> Result<NonNull<u8>, Error> {
1319        // Do not try to access the grant region of an inactive process.
1320        if !self.is_running() {
1321            return Err(Error::InactiveApp);
1322        }
1323
1324        // Retrieve the grant pointer from the `grant_pointers` slice. We use
1325        // `[slice].get()` so that if the grant number is invalid this will
1326        // return `Err` and not panic.
1327        self.grant_pointers
1328            .map_or(Err(Error::KernelError), |grant_pointers| {
1329                // Implement `grant_pointers[grant_num]` without a chance of a
1330                // panic.
1331                match grant_pointers.get_mut(grant_num) {
1332                    Some(grant_entry) => {
1333                        // Check if this is entering a valid grant that has been created and
1334                        // initialized. If the grant is not valid then the `grant_ptr` will
1335                        // be null.
1336                        if let Some(grant_ptr_nonnull) = NonNull::new(grant_entry.grant_ptr) {
1337                            // Check if the grant pointer is marked that the grant has already
1338                            // been entered. If so, return an error.
1339                            if (usize::from(grant_ptr_nonnull.addr())) & 0x1 == 0x1 {
1340                                // Lowest bit is one, meaning this grant has been entered.
1341                                Err(Error::AlreadyInUse)
1342                            } else {
1343                                // Now, to mark that the grant has been entered, we set the lowest
1344                                // bit to one and save this as the grant pointer.
1345                                grant_entry.grant_ptr =
1346                                    grant_ptr_nonnull.map_addr(|a| a | 0x1).as_ptr();
1347
1348                                // And we return the grant pointer to the entered grant.
1349                                Ok(grant_ptr_nonnull)
1350                            }
1351                        } else {
1352                            // The grant has not been created and is not valid to enter.
1353                            Err(Error::OutOfMemory)
1354                        }
1355                    }
1356                    None => Err(Error::AddressOutOfBounds),
1357                }
1358            })
1359    }
1360
1361    fn enter_custom_grant(
1362        &self,
1363        identifier: ProcessCustomGrantIdentifier,
1364    ) -> Result<*mut u8, Error> {
1365        // Do not try to access the grant region of an inactive process.
1366        if !self.is_running() {
1367            return Err(Error::InactiveApp);
1368        }
1369
1370        // Get the address of the custom grant based on the identifier.
1371        let address = self.get_custom_grant_address(identifier);
1372
1373        // We never deallocate custom grants and only we can change the
1374        // `identifier` so we know this is a valid address for the custom grant.
1375        // kernel_memory_break seems like the most reasonable pointer to get the
1376        // provenance from.
1377        Ok(self.kernel_memory_break().with_addr(address).cast_mut())
1378    }
1379
1380    unsafe fn leave_grant(&self, grant_num: usize) {
1381        // Do not modify an inactive process.
1382        if !self.is_running() {
1383            return;
1384        }
1385
1386        self.grant_pointers.map(|grant_pointers| {
1387            // Implement `grant_pointers[grant_num]` without a chance of a
1388            // panic.
1389            if let Some(grant_entry) = grant_pointers.get_mut(grant_num) {
1390                // Get a copy of the actual grant pointer.
1391                let grant_ptr = grant_entry.grant_ptr;
1392
1393                // Now, to mark that the grant has been released, we set the
1394                // lowest bit back to zero and save this as the grant
1395                // pointer.
1396                grant_entry.grant_ptr = grant_ptr.map_addr(|a| a & !0x1);
1397            }
1398        });
1399    }
1400
1401    fn grant_allocated_count(&self) -> Option<usize> {
1402        // Do not modify an inactive process.
1403        if !self.is_running() {
1404            return None;
1405        }
1406
1407        self.grant_pointers.map(|grant_pointers| {
1408            // Filter our list of grant pointers into just the non-null ones,
1409            // and count those. A grant is allocated if its grant pointer is
1410            // non-null.
1411            grant_pointers
1412                .iter()
1413                .filter(|grant_entry| !grant_entry.grant_ptr.is_null())
1414                .count()
1415        })
1416    }
1417
1418    fn lookup_grant_from_driver_num(&self, driver_num: usize) -> Result<usize, Error> {
1419        self.grant_pointers
1420            .map_or(Err(Error::KernelError), |grant_pointers| {
1421                // Filter our list of grant pointers into just the non null
1422                // ones, and count those. A grant is allocated if its grant
1423                // pointer is non-null.
1424                match grant_pointers.iter().position(|grant_entry| {
1425                    // Only consider allocated grants.
1426                    (!grant_entry.grant_ptr.is_null()) && grant_entry.driver_num == driver_num
1427                }) {
1428                    Some(idx) => Ok(idx),
1429                    None => Err(Error::OutOfMemory),
1430                }
1431            })
1432    }
1433
1434    fn is_valid_upcall_function_pointer(&self, upcall_fn: *const ()) -> bool {
1435        let ptr: *const u8 = upcall_fn.cast();
1436        let size = mem::size_of::<*const u8>();
1437
1438        // It is okay if this function is in memory or flash.
1439        self.in_app_flash_memory(ptr, size) || self.in_app_owned_memory(ptr, size)
1440    }
1441
1442    fn get_process_name(&self) -> &'static str {
1443        self.header.get_package_name().unwrap_or("")
1444    }
1445
1446    fn get_completion_code(&self) -> Option<Option<u32>> {
1447        self.completion_code.get()
1448    }
1449
1450    fn set_syscall_return_value(&self, return_value: SyscallReturn) {
1451        match self.stored_state.map(|stored_state| {
1452            // Actually set the return value for a particular process.
1453            //
1454            // SAFETY: The UKB implementation uses the bounds of
1455            // process-accessible memory to verify that any memory changes are
1456            // valid. Here, the unsafe promise we are making is that the bounds
1457            // passed to the UKB are correct. Because we use the start of the
1458            // process's memory, and the current `app_break`, we know that the
1459            // memory in that range is accessible to the process.
1460            unsafe {
1461                self.chip
1462                    .userspace_kernel_boundary()
1463                    .set_syscall_return_value(
1464                        self.mem_start(),
1465                        self.app_break.get(),
1466                        stored_state,
1467                        return_value,
1468                    )
1469            }
1470        }) {
1471            Some(Ok(())) => {
1472                // If we get an `Ok` we are all set.
1473
1474                // The process is either already in the running state (having
1475                // just called a nonblocking syscall like command) or needs to
1476                // be moved to the running state having called Yield-WaitFor and
1477                // now needing to be resumed. Either way we can set the state to
1478                // running.
1479                self.state.set(State::Running);
1480                // The task is running, if it was yielded-for an upcall,
1481                // the upcall must have been scheduled, unset
1482                // the ready flag.
1483                self.is_yield_wait_for_ready.set(false);
1484            }
1485
1486            Some(Err(())) => {
1487                // If we get an `Err`, then the UKB implementation could not set
1488                // the return value, likely because the process's stack is no
1489                // longer accessible to it. All we can do is fault.
1490                self.set_fault_state();
1491            }
1492
1493            None => {
1494                // We should never be here since `stored_state` should always be
1495                // occupied.
1496                self.set_fault_state();
1497            }
1498        }
1499    }
1500
1501    fn set_process_function(&self, callback: FunctionCall) {
1502        // See if we can actually enqueue this function for this process.
1503        // Architecture-specific code handles actually doing this since the
1504        // exact method is both architecture- and implementation-specific.
1505        //
1506        // This can fail, for example if the process does not have enough memory
1507        // remaining.
1508        match self.stored_state.map(|stored_state| {
1509            // Let the UKB implementation handle setting the process's PC so
1510            // that the process executes the upcall function.
1511            //
1512            // SAFETY: We encapsulate unsafe here because we are guaranteeing
1513            // that the memory bounds passed to `set_process_function` are
1514            // correct. We know this because we use the start of process memory
1515            // and the current `app_break`, and that range is accessible to the
1516            // process.
1517            unsafe {
1518                self.chip.userspace_kernel_boundary().set_process_function(
1519                    self.mem_start(),
1520                    self.app_break.get(),
1521                    stored_state,
1522                    callback,
1523                )
1524            }
1525        }) {
1526            Some(Ok(())) => {
1527                // If we got an `Ok` we are all set and should mark that this
1528                // process is ready to be scheduled.
1529
1530                // Move this process to the "running" state so the scheduler
1531                // will schedule it.
1532                self.state.set(State::Running);
1533            }
1534
1535            Some(Err(())) => {
1536                // If we got an Error, then there was likely not enough room on
1537                // the stack to allow the process to execute this function given
1538                // the details of the particular architecture this is running
1539                // on. This process has essentially faulted, so we mark it as
1540                // such.
1541                self.set_fault_state();
1542            }
1543
1544            None => {
1545                // We should never be here since `stored_state` should always be
1546                // occupied.
1547                self.set_fault_state();
1548            }
1549        }
1550    }
1551
1552    unsafe fn switch_to(&self) -> Option<syscall::ContextSwitchReason> {
1553        // Cannot switch to an invalid process
1554        if !self.is_running() {
1555            return None;
1556        }
1557
1558        let (switch_reason, stack_pointer) =
1559            self.stored_state.map_or((None, None), |stored_state| {
1560                // Switch to the process.
1561                //
1562                // SAFETY: We guarantee that the memory pointers we pass are valid,
1563                // ensuring this context switch is safe. We know this because we use
1564                // the start of process memory and the current `app_break`, and that
1565                // range is accessible to the process. Therefore we encapsulate the
1566                // `unsafe`. Also, the safety requirements for `switch_to` ensure
1567                // the MPU is correctly configured.
1568                unsafe {
1569                    let (switch_reason, optional_stack_pointer) = self
1570                        .chip
1571                        .userspace_kernel_boundary()
1572                        .switch_to_process(self.mem_start(), self.app_break.get(), stored_state);
1573                    (Some(switch_reason), optional_stack_pointer)
1574                }
1575            });
1576
1577        // If the UKB implementation passed us a stack pointer, update our
1578        // debugging state. This is completely optional.
1579        if let Some(sp) = stack_pointer {
1580            self.debug.set_new_app_stack_min_pointer(sp);
1581        }
1582
1583        switch_reason
1584    }
1585
1586    fn debug_syscall_count(&self) -> usize {
1587        self.debug.get_syscall_count()
1588    }
1589
1590    fn debug_dropped_upcall_count(&self) -> usize {
1591        self.debug.get_dropped_upcall_count()
1592    }
1593
1594    fn debug_timeslice_expiration_count(&self) -> usize {
1595        self.debug.get_timeslice_expiration_count()
1596    }
1597
1598    fn debug_timeslice_expired(&self) {
1599        self.debug.increment_timeslice_expiration_count();
1600    }
1601
1602    fn debug_syscall_called(&self, last_syscall: Syscall) {
1603        self.debug.increment_syscall_count();
1604        self.debug.set_last_syscall(last_syscall);
1605    }
1606
1607    fn debug_syscall_last(&self) -> Option<Syscall> {
1608        self.debug.get_last_syscall()
1609    }
1610
1611    fn get_addresses(&self) -> ProcessAddresses {
1612        ProcessAddresses {
1613            flash_start: self.flash_start() as usize,
1614            flash_non_protected_start: self.flash_non_protected_start(),
1615            flash_integrity_end: self
1616                .flash
1617                .as_ptr()
1618                .wrapping_add(self.header.get_binary_end() as usize),
1619            flash_end: self.flash_end(),
1620            sram_start: self.mem_start() as usize,
1621            sram_app_brk: self.app_memory_break() as usize,
1622            sram_grant_start: self.kernel_memory_break() as usize,
1623            sram_end: self.mem_end() as usize,
1624            sram_heap_start: self.debug.get_app_heap_start_pointer().map(|p| p as usize),
1625            sram_stack_top: self.debug.get_app_stack_start_pointer().map(|p| p as usize),
1626            sram_stack_bottom: self.debug.get_app_stack_min_pointer().map(|p| p as usize),
1627        }
1628    }
1629
1630    fn get_sizes(&self) -> ProcessSizes {
1631        ProcessSizes {
1632            grant_pointers: mem::size_of::<GrantPointerEntry>()
1633                * self.kernel.get_grant_count_and_finalize(),
1634            upcall_list: Self::CALLBACKS_SIZE,
1635            process_control_block: Self::PROCESS_STRUCT_SIZE,
1636        }
1637    }
1638
1639    fn print_full_process(&self, writer: &mut dyn Write) {
1640        if !config::CONFIG.debug_panics {
1641            return;
1642        }
1643
1644        self.stored_state.map(|stored_state| {
1645            // SAFETY: We guarantee the memory bounds pointers provided to the
1646            // UKB are correct. We know this because we use the start of process
1647            // memory and the current `app_break`, and that range is accessible
1648            // to the process.
1649            unsafe {
1650                self.chip.userspace_kernel_boundary().print_context(
1651                    self.mem_start(),
1652                    self.app_break.get(),
1653                    stored_state,
1654                    writer,
1655                );
1656            }
1657        });
1658
1659        // Display grant information.
1660        let number_grants = self.kernel.get_grant_count_and_finalize();
1661        let _ = writer.write_fmt(format_args!(
1662            "\
1663            \r\n Total number of grant regions defined: {}\r\n",
1664            self.kernel.get_grant_count_and_finalize()
1665        ));
1666        let rows = number_grants.div_ceil(3);
1667
1668        // Access our array of grant pointers.
1669        self.grant_pointers.map(|grant_pointers| {
1670            // Iterate each grant and show its address.
1671            for i in 0..rows {
1672                for j in 0..3 {
1673                    let index = i + (rows * j);
1674                    if index >= number_grants {
1675                        break;
1676                    }
1677
1678                    // Implement `grant_pointers[grant_num]` without a chance of
1679                    // a panic.
1680                    grant_pointers.get(index).map(|grant_entry| {
1681                        if grant_entry.grant_ptr.is_null() {
1682                            let _ =
1683                                writer.write_fmt(format_args!("  Grant {:>2} : --        ", index));
1684                        } else {
1685                            let _ = writer.write_fmt(format_args!(
1686                                "  Grant {:>2} {:#x}: {:p}",
1687                                index, grant_entry.driver_num, grant_entry.grant_ptr
1688                            ));
1689                        }
1690                    });
1691                }
1692                let _ = writer.write_fmt(format_args!("\r\n"));
1693            }
1694        });
1695
1696        // Display the current state of the MPU for this process.
1697        self.mpu_config.map(|config| {
1698            let _ = writer.write_fmt(format_args!("{}", config));
1699        });
1700
1701        // Print a helpful message on how to re-compile a process to view the
1702        // listing file. If a process is PIC, then we also need to print the
1703        // actual addresses the process executed at so that the .lst file can be
1704        // generated for those addresses. If the process was already compiled
1705        // for a fixed address, then just generating a .lst file is fine.
1706
1707        if self.debug.get_fixed_address_flash().is_some() {
1708            // Fixed addresses, can just run `make lst`.
1709            let _ = writer.write_fmt(format_args!(
1710                "\
1711                    \r\nTo debug libtock-c apps, run `make lst` in the app's\
1712                    \r\nfolder and open the arch.{:#x}.{:#x}.lst file.\r\n\r\n",
1713                self.debug.get_fixed_address_flash().unwrap_or(0),
1714                self.debug.get_fixed_address_ram().unwrap_or(0)
1715            ));
1716        } else {
1717            // PIC, need to specify the addresses.
1718            let sram_start = self.mem_start() as usize;
1719            let flash_start = self.flash.as_ptr() as usize;
1720            let flash_init_fn = flash_start + self.header.get_init_function_offset() as usize;
1721
1722            let _ = writer.write_fmt(format_args!(
1723                "\
1724                    \r\nTo debug libtock-c apps, run\
1725                    \r\n`make debug RAM_START={:#x} FLASH_INIT={:#x}`\
1726                    \r\nin the app's folder and open the .lst file.\r\n\r\n",
1727                sram_start, flash_init_fn
1728            ));
1729        }
1730    }
1731
1732    fn get_stored_state(&self, out: &mut [u8]) -> Result<usize, ErrorCode> {
1733        self.stored_state
1734            .map(|stored_state| {
1735                self.chip
1736                    .userspace_kernel_boundary()
1737                    .store_context(stored_state, out)
1738            })
1739            .unwrap_or(Err(ErrorCode::FAIL))
1740    }
1741}
1742
1743impl<C: 'static + Chip, D: 'static + ProcessStandardDebug> ProcessStandard<'_, C, D> {
1744    /// Alignment requirement for each `GrantPointerEntry` in the grant pointers
1745    /// slice.
1746    const GRANT_POINTERS_ALIGNMENT: usize = mem::align_of::<GrantPointerEntry>();
1747
1748    /// Number of upcalls stored in the upcall ring buffer (10 element length).
1749    const CALLBACK_LEN: usize = 10;
1750    /// Size of the upcall storage buffer.
1751    ///
1752    /// As of June 2026, we cannot do
1753    ///
1754    /// ```ignore
1755    /// const CALLBACKS_SIZE usize = mem::size_of::<MaybeUninit<[Task; Self::CALLBACK_LEN]>>();
1756    /// ```
1757    ///
1758    /// because of the error:
1759    ///
1760    /// ```text
1761    /// error: generic `Self` types are currently not permitted in anonymous constants
1762    ///     --> kernel/src/process_standard.rs:1712:70
1763    ///      |
1764    /// 1712 |     const CALLBACKS_SIZE: usize = mem::size_of::<MaybeUninit<[Task; Self::CALLBACK_LEN]>>();
1765    ///      |                                                                      ^^^^
1766    ///      |
1767    /// ```
1768    const CALLBACKS_SIZE: usize = mem::size_of::<Task>() * Self::CALLBACK_LEN;
1769    /// Alignment requirement of the upcall storage buffer.
1770    const CALLBACKS_ALIGNMENT: usize = mem::align_of::<Task>();
1771
1772    // Memory offset to make room for this process's control block.
1773    const PROCESS_STRUCT_SIZE: usize = mem::size_of::<ProcessStandard<C, D>>();
1774    /// Alignment requirement for `ProcessStandard`.
1775    const PROCESS_STRUCT_ALIGNMENT: usize = mem::align_of::<ProcessStandard<C, D>>();
1776
1777    /// Create a `ProcessStandard` object based on the found `ProcessBinary`.
1778    ///
1779    /// # Safety
1780    ///
1781    /// This function allocates memory from `remaining_memory` for use by the
1782    /// process. There must not be any references to or other uses of
1783    /// `remaining_memory` when calling this function.
1784    pub(crate) unsafe fn create(
1785        kernel: &'static Kernel,
1786        chip: &'static C,
1787        pb: ProcessBinary,
1788        remaining_memory: *mut [u8],
1789        fault_policy: &'static dyn ProcessFaultPolicy,
1790        storage_permissions_policy: &'static dyn ProcessStandardStoragePermissionsPolicy<C, D>,
1791        app_id: ShortId,
1792        index: usize,
1793    ) -> Result<(Option<&'static dyn Process>, *mut [u8]), (ProcessLoadError, *mut [u8])> {
1794        let process_name = pb.header.get_package_name();
1795        let process_ram_requested_size = pb.header.get_minimum_app_ram_size() as usize;
1796
1797        // Initialize MPU region configuration.
1798        let mut mpu_config = match chip.mpu().new_config() {
1799            Some(mpu_config) => mpu_config,
1800            None => return Err((ProcessLoadError::MpuConfigurationError, remaining_memory)),
1801        };
1802
1803        // Allocate MPU region for flash.
1804        if chip
1805            .mpu()
1806            .allocate_region(
1807                pb.flash.as_ptr(),
1808                pb.flash.len(),
1809                pb.flash.len(),
1810                mpu::Permissions::ReadExecuteOnly,
1811                &mut mpu_config,
1812            )
1813            .is_none()
1814        {
1815            if config::CONFIG.debug_load_processes {
1816                debug!(
1817                    "[!] flash={:#010X}-{:#010X} process={:?} - couldn't allocate MPU region for flash",
1818                    pb.flash.as_ptr() as usize,
1819                    pb.flash.as_ptr() as usize + pb.flash.len() - 1,
1820                    process_name
1821                );
1822            }
1823            return Err((ProcessLoadError::MpuInvalidFlashLength, remaining_memory));
1824        }
1825
1826        // Determine how much space we need in the application's memory space
1827        // just for kernel and grant state. We need to make sure we allocate
1828        // enough memory just for that.
1829
1830        // Calculate how many bytes we need for grant pointers.
1831        let grant_ptr_size = mem::size_of::<GrantPointerEntry>();
1832        let grant_ptrs_num = kernel.get_grant_count_and_finalize();
1833        let grant_ptrs_size = grant_ptrs_num * grant_ptr_size;
1834
1835        // Initial size of the kernel-owned part of process memory can be
1836        // calculated directly based on the initial size of all kernel-owned
1837        // data structures.
1838        //
1839        // Add the alignment size of each data structure to handle the case
1840        // where the memory region starts at the worst possible address and we
1841        // need to add padding. Note: the maximum shift will only ever be one
1842        // less than the alignment size, but to avoid unusual addresses we just
1843        // use the full alignment.
1844        let initial_kernel_memory_size = grant_ptrs_size
1845            + Self::GRANT_POINTERS_ALIGNMENT
1846            + Self::CALLBACKS_SIZE
1847            + Self::CALLBACKS_ALIGNMENT
1848            + Self::PROCESS_STRUCT_SIZE
1849            + Self::PROCESS_STRUCT_ALIGNMENT;
1850
1851        // By default we start with the initial size of process-accessible
1852        // memory set to 0. This maximizes the flexibility that processes have
1853        // to allocate their memory as they see fit. If a process needs more
1854        // accessible memory it must use the `brk` memop syscalls to request
1855        // more memory.
1856        //
1857        // We must take into account any process-accessible memory required by
1858        // the context switching implementation and allocate at least that much
1859        // memory so that we can successfully switch to the process. This is
1860        // architecture and implementation specific, so we query that now.
1861        let min_process_memory_size = chip
1862            .userspace_kernel_boundary()
1863            .initial_process_app_brk_size();
1864
1865        // We have to ensure that we at least ask the MPU for
1866        // `min_process_memory_size` so that we can be sure that `app_brk` is
1867        // not set inside the kernel-owned memory region. Now, in practice,
1868        // processes should not request 0 (or very few) bytes of memory in their
1869        // TBF header (i.e. `process_ram_requested_size` will almost always be
1870        // much larger than `min_process_memory_size`), as they are unlikely to
1871        // work with essentially no available memory. But, we still must protect
1872        // for that case.
1873        let min_process_ram_size = cmp::max(process_ram_requested_size, min_process_memory_size);
1874
1875        // Minimum memory size for the process.
1876        let min_total_memory_size = min_process_ram_size + initial_kernel_memory_size;
1877
1878        // Check if this process requires a fixed memory start address. If so,
1879        // try to adjust the memory region to work for this process.
1880        //
1881        // Right now, we only support skipping some RAM and leaving a chunk
1882        // unused so that the memory region starts where the process needs it
1883        // to.
1884        let remaining_memory = if let Some(fixed_memory_start) = pb
1885            .header
1886            .get_fixed_address_ram()
1887            .map(|addr: u32| remaining_memory.cast::<u8>().with_addr(addr as usize))
1888        {
1889            // The process does have a fixed address.
1890            if fixed_memory_start == remaining_memory.cast() {
1891                // Address already matches.
1892                remaining_memory
1893            } else if fixed_memory_start > remaining_memory.cast() {
1894                // Process wants a memory address farther in memory. Try to
1895                // advance the memory region to make the address match.
1896                let diff = fixed_memory_start.addr() - remaining_memory.addr();
1897                if diff > remaining_memory.len() {
1898                    // We ran out of memory.
1899                    let actual_address = (remaining_memory.cast::<u8>())
1900                        .wrapping_byte_add(remaining_memory.len())
1901                        .wrapping_byte_sub(1);
1902                    let expected_address = fixed_memory_start;
1903                    return Err((
1904                        ProcessLoadError::MemoryAddressMismatch {
1905                            actual_address,
1906                            expected_address,
1907                        },
1908                        remaining_memory,
1909                    ));
1910                } else {
1911                    // Change the memory range to start where the process requested it.
1912                    // Because of the if statement above we know this should work. Doing
1913                    // it more cleanly would be good but was a bit beyond my borrow ken;
1914                    // calling get_mut has a mutable borrow.-pal
1915                    //
1916                    // SAFETY: `diff` must be within the `remaining_memory` slice. Because we
1917                    // check that `diff` is less than the length of `remaining_memory`
1918                    // we know diff will be within  `remaining_memory`.
1919                    let (_, sliced) = unsafe { raw_slice_split_at_mut(remaining_memory, diff) };
1920                    sliced
1921                }
1922            } else {
1923                // Address is earlier in memory, nothing we can do.
1924                let actual_address = remaining_memory.cast();
1925                let expected_address = fixed_memory_start;
1926                return Err((
1927                    ProcessLoadError::MemoryAddressMismatch {
1928                        actual_address,
1929                        expected_address,
1930                    },
1931                    remaining_memory,
1932                ));
1933            }
1934        } else {
1935            remaining_memory
1936        };
1937
1938        // Determine where process memory will go and allocate an MPU region.
1939        //
1940        // `[allocation_start, allocation_size)` will cover both
1941        //
1942        // - the app-owned `min_process_memory_size`-long part of memory (at
1943        //   some offset within `remaining_memory`), as well as
1944        //
1945        // - the kernel-owned allocation growing downward starting at the end
1946        //   of this allocation, `initial_kernel_memory_size` bytes long.
1947        //
1948        let (allocation_start, allocation_size) = match chip.mpu().allocate_app_memory_region(
1949            remaining_memory.cast(),
1950            remaining_memory.len(),
1951            min_total_memory_size,
1952            min_process_memory_size,
1953            initial_kernel_memory_size,
1954            mpu::Permissions::ReadWriteOnly,
1955            &mut mpu_config,
1956        ) {
1957            Some((memory_start, memory_size)) => (memory_start, memory_size),
1958            None => {
1959                // Failed to load process. Insufficient memory.
1960                if config::CONFIG.debug_load_processes {
1961                    debug!(
1962                        "[!] flash={:#010X}-{:#010X} process={:?} - couldn't allocate memory region of size >= {:#X}",
1963                        pb.flash.as_ptr() as usize,
1964                        pb.flash.as_ptr() as usize + pb.flash.len() - 1,
1965                        process_name,
1966                        min_total_memory_size
1967                    );
1968                }
1969                return Err((ProcessLoadError::NotEnoughMemory, remaining_memory));
1970            }
1971        };
1972
1973        // Determine the offset of the app-owned part of the above memory
1974        // allocation. An MPU may not place it at the very start of
1975        // `remaining_memory` for internal alignment constraints. This can only
1976        // overflow if the MPU implementation is incorrect; a compliant
1977        // implementation must return a memory allocation within the
1978        // `remaining_memory` slice.
1979        let app_memory_start_offset = allocation_start.addr() - remaining_memory.addr();
1980
1981        // Check if the memory region is valid for the process. If a process
1982        // included a fixed address for the start of RAM in its TBF header (this
1983        // field is optional, processes that are position independent do not
1984        // need a fixed address) then we check that we used the same address
1985        // when we allocated it in RAM.
1986        if let Some(fixed_memory_start) = pb
1987            .header
1988            .get_fixed_address_ram()
1989            .map(|addr: u32| remaining_memory.cast::<u8>().with_addr(addr as usize))
1990        {
1991            let actual_address = remaining_memory
1992                .cast::<u8>()
1993                .wrapping_byte_add(app_memory_start_offset);
1994            let expected_address = fixed_memory_start;
1995            if actual_address != expected_address {
1996                return Err((
1997                    ProcessLoadError::MemoryAddressMismatch {
1998                        actual_address,
1999                        expected_address,
2000                    },
2001                    remaining_memory,
2002                ));
2003            }
2004        }
2005
2006        // With our MPU allocation, we can begin to divide up the
2007        // `remaining_memory` slice into individual regions for the process and
2008        // kernel, as follows:
2009        //
2010        //
2011        //  ┌───────────────────────────────────────────────────────────────────────────────────────
2012        //  │ remaining_memory
2013        //  └───────────────────────────────────────────────────────────────────────────────────────
2014        //  ┆                                                                        ┆
2015        //  ┌────────────────────────────────────────────────────────────────────────┬──────────────
2016        //  │ allocated_padded_memory                                                │ unused_memory
2017        //  └────────────────────────────────────────────────────────────────────────┴──────────────
2018        //      ┆                                                                    ┆
2019        //      ┌────────────────────────────────────────────────────────────────────┐
2020        //  ┆←─→│ allocated_memory                                                   │
2021        //    ↑ └────────────────────────────────────────────────────────────────────┘
2022        //    └┄┄┄app_memory_start_offset                                            ┆
2023        //      ┌─────────────────────────┬──────────────────────────────────────────┐
2024        //      │ app_accessible_memory   │ allocated_kernel_memory                  │
2025        //      └─────────────────────────┴──────────────────────────────────────────┘
2026        //      ┆←min_process_memory_size→┆←────→┆←────initial_kernel_memory_size───→┆
2027        //                                ↑  ↑   ┆                                   ┆
2028        //              initial_app_brk┄┄┄┘  ┆   ┆ ┌┄┄┄kernel_memory_break           ┆
2029        //           initially unallocated┄┄┄┘   ┆ ↓                                 ┆
2030        //                                       ┆ ┌───────┬──────────┬──────────────┐
2031        //                                       ┆↔│process│upcall_buf│grant_pointers│
2032        //                                       ┆ └───────┴──────────┴──────────────┘
2033        //                                        ↑       ↑          ↑              ↑
2034        //             possible alignment padding┄┴┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
2035        //
2036        //
2037        // First split the `remaining_memory` into two slices:
2038        //
2039        // 1. `allocated_padded_memory`: the allocated memory region, containing:
2040        //
2041        //    1. optional padding at the start of the memory region of
2042        //       `app_memory_start_offset` bytes,
2043        //    2. the app accessible memory region of `min_process_memory_size`,
2044        //    3. optional unallocated memory, and
2045        //    4. kernel-reserved memory, growing downward starting at the end of
2046        //       `allocated_memory`.
2047        //
2048        // 2. `unused_memory`: the rest of the `remaining_memory`, not assigned
2049        //    to this app.
2050        //
2051        // SAFETY: `app_memory_start_offset + allocation_size` must be within `remaining_memory`.
2052        let (allocated_padded_memory, unused_memory) = unsafe {
2053            raw_slice_split_at_mut(remaining_memory, app_memory_start_offset + allocation_size)
2054        };
2055
2056        // Now, slice off the (optional) padding at the start:
2057        //
2058        // SAFETY: `app_memory_start_offset` must be within `allocated_padded_memory`.
2059        let (_padding, allocated_memory) =
2060            unsafe { raw_slice_split_at_mut(allocated_padded_memory, app_memory_start_offset) };
2061
2062        // We continue to sub-slice the `allocated_memory` into
2063        // process-accessible and kernel-owned memory. Prior to that, store the
2064        // start and length ofthe overall allocation:
2065        let allocated_memory_start = allocated_memory.cast();
2066        let allocated_memory_len = allocated_memory.len();
2067
2068        // Slice off the process-accessible memory:
2069        //
2070        // SAFETY: `min_process_memory_size` must be within `allocated_memory`.
2071        let (app_accessible_memory, allocated_kernel_memory) =
2072            unsafe { raw_slice_split_at_mut(allocated_memory, min_process_memory_size) };
2073
2074        // Initialize (zero) the initial process-accessible memory region. This
2075        // serves two purposes:
2076        //
2077        // 1. It prevents a process from accessing any information still
2078        //    contained in this memory from prior kernel instances or processes.
2079        //
2080        // 2. It satisfies Rust's requirements that all dereferencable memory be
2081        //    properly initialized. This is important, as we'll be creating
2082        //    references into this process-accessible memory region through the
2083        //    process buffer infrastructure.
2084        let app_accessible_memory_bytes: *mut u8 = app_accessible_memory.cast();
2085        // SAFETY: `app_accessible_memory_bytes` is from a slice, and we use that
2086        // slice's length, so we know that there is enough memory and that the
2087        // pointer is aligned.
2088        unsafe {
2089            core::ptr::write_bytes(
2090                app_accessible_memory_bytes,
2091                // Set the entire app-accessible memory region to `0`:
2092                0_u8,
2093                app_accessible_memory.len(),
2094            );
2095        }
2096
2097        // Set the initial process-accessible memory.
2098        //
2099        // SAFETY: By using the slice `app_accessible_memory` and getting a pointer to
2100        // the byte after the slice, we are ensured that the memory between the
2101        // start of the allocation and the new pointer (at the end of the slice)
2102        // is valid because of the existing slice.
2103        let initial_app_brk = unsafe {
2104            app_accessible_memory
2105                .cast::<u8>()
2106                .add(app_accessible_memory.len())
2107        };
2108
2109        // Set the initial allow high water mark to the start of process memory
2110        // since no `allow` calls have been made yet.
2111        let initial_allow_high_water_mark = app_accessible_memory.cast();
2112
2113        // Set up initial grant region.
2114        //
2115        // `kernel_memory_break` is set to the end of kernel-accessible memory
2116        // and grows downward.
2117        let mut kernel_memory_break: *mut u8 = allocated_kernel_memory
2118            .cast::<u8>()
2119            .wrapping_add(allocated_kernel_memory.len());
2120
2121        ////////////////////////
2122        // Grant Region Pointers
2123        ////////////////////////
2124
2125        // Now that we know we have the space we can setup the grant pointers.
2126        //
2127        // First, move `kernel_memory_break` up to make room for the grant pointers.
2128        kernel_memory_break = kernel_memory_break.wrapping_sub(grant_ptrs_size);
2129        // Next, use the extra alignment padding we factored in to the total
2130        // calculation of `initial_kernel_memory_size` to ensure that
2131        // `kernel_memory_break` is aligned to a `GrantPointerEntry`.
2132        kernel_memory_break = kernel_memory_break
2133            .wrapping_sub(kernel_memory_break as usize % Self::GRANT_POINTERS_ALIGNMENT);
2134
2135        // Create the `GrantPointerEntry`s in the kernel region, then initialize
2136        // them.
2137        //
2138        // Where we calculated the updated kernel_memory_break is where the
2139        // `GrantPointerEntry`s start.
2140        let grant_pointers_memory_location: *mut MaybeUninit<GrantPointerEntry> =
2141            kernel_memory_break.cast();
2142        // Get a reference to the slice of `GrantPointerEntry`s.
2143        //
2144        // SAFETY: This is safe, as `grant_pointers_memory_location` is aligned to a
2145        // `GrantPointerEntry`, and we ensured there is space for
2146        // `grant_ptrs_num` of `GrantPointerEntry`s allocated.
2147        let grant_pointers_uninit: &mut [MaybeUninit<GrantPointerEntry>] =
2148            unsafe { slice::from_raw_parts_mut(grant_pointers_memory_location, grant_ptrs_num) };
2149        // Set all grant pointers to null.
2150        for grant_entry in grant_pointers_uninit.iter_mut() {
2151            grant_entry.write(GrantPointerEntry {
2152                driver_num: 0,
2153                grant_ptr: core::ptr::null_mut(),
2154            });
2155        }
2156        // SAFETY: All values in this slice have been properly initialized.
2157        let grant_pointers = unsafe { maybe_uninit_slice_assume_init_mut(grant_pointers_uninit) };
2158
2159        ////////////////////////
2160        // Upcall Queue
2161        ////////////////////////
2162
2163        // Now that we know we have the space we can setup the memory for the
2164        // upcalls.
2165        //
2166        // Move our `kernel_memory_break` up the size of the callback slice.
2167        kernel_memory_break = kernel_memory_break.wrapping_sub(Self::CALLBACKS_SIZE);
2168        // Use the space we allocated for alignment in case the pointer is not aligned.
2169        kernel_memory_break = kernel_memory_break
2170            .wrapping_sub(kernel_memory_break as usize % Self::CALLBACKS_ALIGNMENT);
2171
2172        // Set up ring buffer for upcalls to the process. The memory is uninitialized here,
2173        // so we cast to MaybeUninit<Task> which accurately represents that state.
2174        let upcall_buf: *mut core::mem::MaybeUninit<Task> = kernel_memory_break.cast();
2175
2176        // Get a reference `&mut [Task; Self:CALLBACK_LEN]`
2177        //
2178        // SAFETY: This needs to be aligned and have allocated space for
2179        // `Self::CALLBACK_LEN` instances of `Task`. We ensured there is enough
2180        // space when we allocated `allocated_kernel_memory` and we moved
2181        // kernel_memory_break up to fit the callbacks. We ensured this is
2182        // aligned by moving `kernel_memory_break` up if needed, and we
2183        // accounted for that potential increase in size when we allocated
2184        // `allocated_kernel_memory`.
2185        let upcall_buf = unsafe { slice::from_raw_parts_mut(upcall_buf, Self::CALLBACK_LEN) };
2186        // Actually setup the ring buffer.
2187        let tasks = RingBuffer::new(upcall_buf);
2188
2189        ////////////////////////
2190        // ProcessStandard
2191        ////////////////////////
2192
2193        // Last thing in the kernel region of process RAM is the process struct.
2194        //
2195        // Move `kernel_memory_break` to make room for the `ProcessStandard` struct.
2196        kernel_memory_break = kernel_memory_break.wrapping_sub(Self::PROCESS_STRUCT_SIZE);
2197        // Use the space we allocated for alignment in case the pointer is not aligned.
2198        kernel_memory_break = kernel_memory_break
2199            .wrapping_sub(kernel_memory_break as usize % Self::PROCESS_STRUCT_ALIGNMENT);
2200
2201        // Create a pointer to where the `ProcessStandard` struct will go in the
2202        // app grant region.
2203        let process_struct_memory_location: *mut MaybeUninit<ProcessStandard<'static, C, D>> =
2204            kernel_memory_break.cast();
2205        // Get a reference to the uninitialized `ProcessStandard` object.
2206        //
2207        // Note, this requires every field be explicitly initialized, as we are
2208        // just transforming a pointer into a structure. Because the
2209        // `ProcessStandard` is not initialized we mark it with `MaybeUninit`.
2210        //
2211        // SAFETY: This must have sufficient allocated space and proper alignment. When
2212        // we sized `allocated_kernel_memory` we ensured there was room for the
2213        // entire `ProcessStandard` struct. We also allocated space for
2214        // potential alignment issues, and ensured `kernel_memory_break` was
2215        // properly aligned for `ProcessStandard`.
2216        let process_uninit: &mut MaybeUninit<ProcessStandard<C, D>> =
2217            unsafe { &mut *process_struct_memory_location };
2218
2219        // Initialize ALL fields of `ProcessStandard`.
2220        //
2221        // SAFETY: These need to be valid and aligned writes. When we create the `MaybeUnint`
2222        // ProcessStandard struct we ensure there is valid memory for the object and
2223        // that it is aligned.
2224        unsafe {
2225            init_uninit_struct!(process_uninit => ProcessStandard<C, D> {
2226                process_id: Cell::new(ProcessId::new(
2227                    kernel,
2228                    kernel.create_process_identifier(),
2229                    index,
2230                )),
2231                app_id: app_id,
2232                kernel: kernel,
2233                chip: chip,
2234                allow_high_water_mark: Cell::new(initial_allow_high_water_mark),
2235                memory_start: allocated_memory_start,
2236                memory_len: allocated_memory_len,
2237                header: pb.header,
2238                kernel_memory_break: Cell::new(kernel_memory_break),
2239                app_break: Cell::new(initial_app_brk),
2240                grant_pointers: MapCell::new(grant_pointers),
2241
2242                credential: pb.credential.get(),
2243                footers: pb.footers,
2244                flash: pb.flash,
2245
2246                stored_state: MapCell::new(Default::default()),
2247                state: Cell::new(State::Yielded),
2248                fault_policy: fault_policy,
2249                restart_count: Cell::new(0),
2250                completion_code: OptionalCell::empty(),
2251
2252                storage_permissions: Cell::new(StoragePermissions::new_null()),
2253
2254                mpu_config: MapCell::new(mpu_config),
2255                mpu_regions: [
2256                    Cell::new(None),
2257                    Cell::new(None),
2258                    Cell::new(None),
2259                    Cell::new(None),
2260                    Cell::new(None),
2261                    Cell::new(None),
2262                ],
2263                tasks: MapCell::new(tasks),
2264                is_yield_wait_for_ready: Cell::new(false),
2265
2266                debug: D::default(),
2267            });
2268        }
2269
2270        // Convert the originally uninitialized `ProcessStandard` to a proper
2271        // `ProcessStandard` struct reference.
2272        //
2273        // SAFETY: All fields in `ProcessStandard` must be initialized. We guaranteed
2274        // this by using the `init_uninit_struct!()` macro, which causes a
2275        // compiler error if there is a missing field.
2276        let process = unsafe { process_uninit.assume_init_mut() };
2277
2278        // Save copies of these in case the app was compiled for fixed addresses
2279        // for later debugging.
2280        let fixed_address_flash = process.header.get_fixed_address_flash();
2281        let fixed_address_ram = process.header.get_fixed_address_ram();
2282        if let Some(fix_addr_flash) = fixed_address_flash {
2283            process.debug.set_fixed_address_flash(fix_addr_flash);
2284        }
2285        if let Some(fix_addr_ram) = fixed_address_ram {
2286            process.debug.set_fixed_address_ram(fix_addr_ram);
2287        }
2288
2289        // Handle any architecture-specific requirements for a new process.
2290        match process.stored_state.map(|stored_state| {
2291            // SAFETY: NOTE! We have to ensure that the start of process-accessible memory
2292            // (`app_memory_start`) is word-aligned. Since we currently start
2293            // process-accessible memory at the beginning of the allocated memory
2294            // region, we trust the MPU to give us a word-aligned starting address.
2295            //
2296            // TODO: https://github.com/tock/tock/issues/1739
2297            unsafe {
2298                chip.userspace_kernel_boundary().initialize_process(
2299                    app_accessible_memory.cast(),
2300                    initial_app_brk,
2301                    stored_state,
2302                )
2303            }
2304        }) {
2305            Some(Ok(())) => {}
2306            _ => {
2307                if config::CONFIG.debug_load_processes {
2308                    debug!(
2309                        "[!] flash={:#010X}-{:#010X} process={:?} - couldn't initialize process",
2310                        pb.flash.as_ptr() as usize,
2311                        pb.flash.as_ptr() as usize + pb.flash.len() - 1,
2312                        process_name
2313                    );
2314                }
2315                // Note that since remaining_memory was split by split_at_mut into
2316                // application memory and unused_memory, a failure here will leak
2317                // the application memory. Not leaking it requires being able to
2318                // reconstitute the original memory slice.
2319                return Err((ProcessLoadError::InternalError, unused_memory));
2320            }
2321        }
2322
2323        let flash_start: *const u8 = process.flash.as_ptr();
2324        let app_start =
2325            flash_start.wrapping_add(process.header.get_app_start_offset() as usize) as usize;
2326        let init_addr: *const () = flash_start
2327            .wrapping_add(process.header.get_init_function_offset() as usize)
2328            .cast();
2329        let fn_base = flash_start as usize;
2330        let fn_len = process.flash.len();
2331
2332        // We need to construct a capability with sufficient authority to cover
2333        // all of a user's code, with permissions to execute it. The entirety
2334        // of this process's flash is sufficient.
2335        //
2336        // SAFETY: It must be safe for this process to access the
2337        // bounds+permission expressed here while assuming no other protection
2338        // mechanism is active.
2339        //  - It is valid under Tock's threat model for a process to try to
2340        //  execute anything within process-owned flash.
2341        //  - `process.flash` which we use to derive the bounds is defined as
2342        //  process-owned flash for a well-formed process, which we trust is
2343        //  the case here.
2344        //  - We grant only execute permission.
2345        //  - We only pass this pointer to this process.
2346        let init_fn = unsafe {
2347            CapabilityPtr::new_with_authority(
2348                init_addr,
2349                fn_base,
2350                fn_len,
2351                CapabilityPtrPermissions::Execute,
2352            )
2353        };
2354
2355        process.tasks.map(|tasks| {
2356            tasks.enqueue(Task::FunctionCall(FunctionCall {
2357                source: FunctionCallSource::Kernel,
2358                pc: init_fn,
2359                argument0: app_start,
2360                argument1: process.memory_start as usize,
2361                argument2: process.memory_len,
2362                argument3: (process.app_break.get() as usize).into(),
2363            }));
2364        });
2365
2366        // Set storage permissions. Put this at the end so that `process` is
2367        // completely formed before using it to determine the storage
2368        // permissions.
2369        process
2370            .storage_permissions
2371            .set(storage_permissions_policy.get_permissions(process));
2372
2373        // Return the process object and a remaining memory for processes slice.
2374        Ok((Some(process), unused_memory))
2375    }
2376
2377    /// Reset the process, resetting all of its state and re-initializing it so
2378    /// it can start running. Assumes the process is not running but is still in
2379    /// flash and still has its memory region allocated to it.
2380    fn reset(&self) -> Result<(), ErrorCode> {
2381        // We need a new process identifier for this process since the restarted
2382        // version is in effect a new process. This is also necessary to
2383        // invalidate any stored `ProcessId`s that point to the old version of
2384        // the process. However, the process has not moved locations in the
2385        // processes array, so we copy the existing index.
2386        let old_index = self.process_id.get().index;
2387        let new_identifier = self.kernel.create_process_identifier();
2388        self.process_id
2389            .set(ProcessId::new(self.kernel, new_identifier, old_index));
2390
2391        // Reset debug information that is per-execution and not per-process.
2392        self.debug.reset_last_syscall();
2393        self.debug.reset_syscall_count();
2394        self.debug.reset_dropped_upcall_count();
2395        self.debug.reset_timeslice_expiration_count();
2396
2397        // Reset MPU region configuration.
2398        //
2399        // TODO: ideally, this would be moved into a helper function used by
2400        // both create() and reset(), but process load debugging complicates
2401        // this. We just want to create new config with only flash and memory
2402        // regions.
2403        //
2404        // We must have a previous MPU configuration stored, fault the
2405        // process if this invariant is violated. We avoid allocating
2406        // a new MPU configuration, as this may eventually exhaust the
2407        // number of available MPU configurations.
2408        let mut mpu_config = self.mpu_config.take().ok_or(ErrorCode::FAIL)?;
2409        self.chip.mpu().reset_config(&mut mpu_config);
2410
2411        // Allocate MPU region for flash.
2412        let app_mpu_flash = self.chip.mpu().allocate_region(
2413            self.flash.as_ptr(),
2414            self.flash.len(),
2415            self.flash.len(),
2416            mpu::Permissions::ReadExecuteOnly,
2417            &mut mpu_config,
2418        );
2419        if app_mpu_flash.is_none() {
2420            // We were unable to allocate an MPU region for flash. This is very
2421            // unexpected since we previously ran this process. However, we
2422            // return now and leave the process faulted and it will not be
2423            // scheduled.
2424            return Err(ErrorCode::FAIL);
2425        }
2426
2427        // RAM
2428
2429        // Re-determine the minimum amount of RAM the kernel must allocate to
2430        // the process based on the specific requirements of the syscall
2431        // implementation.
2432        let min_process_memory_size = self
2433            .chip
2434            .userspace_kernel_boundary()
2435            .initial_process_app_brk_size();
2436
2437        // Recalculate initial_kernel_memory_size as was done in create()
2438        let grant_ptr_size = mem::size_of::<GrantPointerEntry>();
2439        let grant_ptrs_num = self.kernel.get_grant_count_and_finalize();
2440        let grant_ptrs_size = grant_ptrs_num * grant_ptr_size;
2441
2442        let initial_kernel_memory_size = grant_ptrs_size
2443            + Self::GRANT_POINTERS_ALIGNMENT
2444            + Self::CALLBACKS_SIZE
2445            + Self::CALLBACKS_ALIGNMENT
2446            + Self::PROCESS_STRUCT_SIZE
2447            + Self::PROCESS_STRUCT_ALIGNMENT;
2448
2449        let app_mpu_mem = self.chip.mpu().allocate_app_memory_region(
2450            self.mem_start(),
2451            self.memory_len,
2452            self.memory_len, //we want exactly as much as we had before restart
2453            min_process_memory_size,
2454            initial_kernel_memory_size,
2455            mpu::Permissions::ReadWriteOnly,
2456            &mut mpu_config,
2457        );
2458        let (app_mpu_mem_start, app_mpu_mem_len) = match app_mpu_mem {
2459            Some((start, len)) => (start, len),
2460            None => {
2461                // We couldn't configure the MPU for the process. This shouldn't
2462                // happen since we were able to start the process before, but at
2463                // this point it is better to leave the app faulted and not
2464                // schedule it.
2465                return Err(ErrorCode::NOMEM);
2466            }
2467        };
2468
2469        // Reset memory pointers now that we know the layout of the process
2470        // memory and know that we can configure the MPU.
2471
2472        // app_brk is set based on minimum syscall size above the start of
2473        // memory.
2474        let app_brk = app_mpu_mem_start.wrapping_add(min_process_memory_size);
2475        self.app_break.set(app_brk);
2476        // kernel_brk is calculated backwards from the end of memory the size of
2477        // the initial kernel data structures.
2478        let kernel_brk = app_mpu_mem_start
2479            .wrapping_add(app_mpu_mem_len)
2480            .wrapping_sub(initial_kernel_memory_size);
2481        self.kernel_memory_break.set(kernel_brk);
2482        // High water mark for `allow`ed memory is reset to the start of the
2483        // process's memory region.
2484        self.allow_high_water_mark.set(app_mpu_mem_start);
2485
2486        // Store the adjusted MPU configuration:
2487        self.mpu_config.replace(mpu_config);
2488
2489        // Handle any architecture-specific requirements for a process when it
2490        // first starts (as it would when it is new).
2491        let ukb_init_process = self.stored_state.map_or(Err(()), |stored_state| {
2492            // SAFETY: The memory bounds must be valid for this process. We know
2493            // this is true here because we use the start of process memory and
2494            // the current `app_brk`, and that range is accessible to the
2495            // process.
2496            unsafe {
2497                self.chip.userspace_kernel_boundary().initialize_process(
2498                    app_mpu_mem_start,
2499                    app_brk,
2500                    stored_state,
2501                )
2502            }
2503        });
2504        match ukb_init_process {
2505            Ok(()) => {}
2506            Err(()) => {
2507                // We couldn't initialize the architecture-specific state for
2508                // this process. This shouldn't happen since the app was able to
2509                // be started before, but at this point the app is no longer
2510                // valid. The best thing we can do now is leave the app as still
2511                // faulted and not schedule it.
2512                return Err(ErrorCode::RESERVE);
2513            }
2514        }
2515
2516        self.restart_count.increment();
2517
2518        // Mark the state as `Yielded` for the scheduler.
2519        self.state.set(State::Yielded);
2520
2521        // And queue up this app to be restarted.
2522        let flash_start: *const u8 = self.flash_start();
2523        let app_start =
2524            flash_start.wrapping_add(self.header.get_app_start_offset() as usize) as usize;
2525        let init_addr: *const () = flash_start
2526            .wrapping_add(self.header.get_init_function_offset() as usize)
2527            .cast();
2528
2529        // We need to construct a capability with sufficient authority to cover
2530        // all of a user's code, with permissions to execute it. The entirety
2531        // of this process's flash is sufficient.
2532        //
2533        // SAFETY: It must be safe for this process to access the
2534        // bounds+permission expressed here while assuming no other protection
2535        // mechanism is active.
2536        //  - It is valid under Tock's threat model for a process to try to
2537        //  execute anything within process-owned flash.
2538        //  - `self.flash` which we use to derive the bounds is defined as
2539        //  process-owned flash for a well-formed process, which we trust is
2540        //  the case here.
2541        //  - We grant only execute permission.
2542        //  - We only pass this pointer to this process.
2543        let init_fn = unsafe {
2544            CapabilityPtr::new_with_authority(
2545                init_addr,
2546                flash_start as usize,
2547                self.flash_end() - (flash_start as usize),
2548                CapabilityPtrPermissions::Execute,
2549            )
2550        };
2551
2552        self.enqueue_task(Task::FunctionCall(FunctionCall {
2553            source: FunctionCallSource::Kernel,
2554            pc: init_fn,
2555            argument0: app_start,
2556            argument1: self.memory_start as usize,
2557            argument2: self.memory_len,
2558            argument3: (self.app_break.get() as usize).into(),
2559        }))
2560    }
2561
2562    /// Checks if the buffer represented by the passed in base pointer and size
2563    /// is within the RAM bounds currently exposed to the processes (i.e. ending
2564    /// at `app_break`). If this method returns `true`, the buffer is guaranteed
2565    /// to be accessible to the process and to not overlap with the grant
2566    /// region.
2567    fn in_app_owned_memory(&self, buf_start_addr: *const u8, size: usize) -> bool {
2568        // TODO: On some platforms, CapabilityPtr has sufficient authority that we
2569        // could skip this check.
2570        // CapabilityPtr needs to make it slightly further, and we need to add
2571        // interfaces that tell us how much assurance it gives on the current
2572        // platform.
2573        let buf_end_addr = buf_start_addr.wrapping_add(size);
2574
2575        buf_end_addr >= buf_start_addr
2576            && buf_start_addr >= self.mem_start()
2577            && buf_end_addr <= self.app_break.get()
2578    }
2579
2580    /// Checks if the buffer represented by the passed in base pointer and size
2581    /// are within the readable region of an application's flash memory.  If
2582    /// this method returns true, the buffer is guaranteed to be readable to the
2583    /// process.
2584    fn in_app_flash_memory(&self, buf_start_addr: *const u8, size: usize) -> bool {
2585        #![allow(
2586            clippy::suspicious_operation_groupings,
2587            reason = "false positive on flash_non_protected_start"
2588        )]
2589
2590        // TODO: On some platforms, CapabilityPtr has sufficient authority that we
2591        // could skip this check.
2592        // CapabilityPtr needs to make it slightly further, and we need to add
2593        // interfaces that tell us how much assurance it gives on the current
2594        // platform.
2595        let buf_end_addr = buf_start_addr.wrapping_add(size);
2596
2597        buf_end_addr >= buf_start_addr
2598            && buf_start_addr.addr() >= self.flash_non_protected_start()
2599            && buf_end_addr.addr() <= self.flash_end()
2600    }
2601
2602    /// Allocate memory in a process's grant region.
2603    ///
2604    /// Ensures that the allocation is of `size` bytes and aligned to `align`
2605    /// bytes.
2606    ///
2607    /// If there is not enough memory, or the MPU cannot isolate the process
2608    /// accessible region from the new kernel memory break after doing the
2609    /// allocation, then this will return `None`.
2610    fn allocate_in_grant_region_internal(&self, size: usize, align: usize) -> Option<NonNull<u8>> {
2611        self.mpu_config.and_then(|config| {
2612            // First, compute the candidate new pointer. Note that at this point
2613            // we have not yet checked whether there is space for this
2614            // allocation or that it meets alignment requirements.
2615            let new_break_unaligned = self.kernel_memory_break.get().wrapping_sub(size);
2616
2617            // Our minimum alignment requirement is two bytes, so that the
2618            // lowest bit of the address will always be zero and we can use it
2619            // as a flag. It doesn't hurt to increase the alignment (except for
2620            // potentially a wasted byte) so we make sure `align` is at least
2621            // two.
2622            let align = cmp::max(align, 2);
2623
2624            // The alignment must be a power of two, 2^a. The expression
2625            // `!(align - 1)` then returns a mask with leading ones, followed by
2626            // `a` trailing zeros.
2627            let alignment_mask = !(align - 1);
2628            let new_break = new_break_unaligned.map_addr(|a| a & alignment_mask);
2629
2630            // Verify there is space for this allocation
2631            if new_break < self.app_break.get() {
2632                None
2633                // Verify it didn't wrap around
2634            } else if new_break > self.kernel_memory_break.get() {
2635                None
2636                // Verify this is compatible with the MPU.
2637            } else if let Err(()) = self.chip.mpu().update_app_memory_region(
2638                self.app_break.get(),
2639                new_break,
2640                mpu::Permissions::ReadWriteOnly,
2641                config,
2642            ) {
2643                None
2644            } else {
2645                // Allocation is valid.
2646
2647                // We always allocate down, so we must lower the
2648                // kernel_memory_break.
2649                self.kernel_memory_break.set(new_break);
2650
2651                // We need `grant_ptr` as a mutable pointer.
2652                let grant_ptr: *mut u8 = new_break.cast_mut();
2653
2654                // SAFETY: Here we are guaranteeing that `grant_ptr` is not null. We can
2655                // ensure this because we just created `grant_ptr` based on the
2656                // process's allocated memory, and we know it cannot be null.
2657                unsafe { Some(NonNull::new_unchecked(grant_ptr)) }
2658            }
2659        })
2660    }
2661
2662    /// Create the identifier for a custom grant that grant.rs uses to access
2663    /// the custom grant.
2664    ///
2665    /// We create this identifier by calculating the number of bytes between
2666    /// where the custom grant starts and the end of the process memory.
2667    fn create_custom_grant_identifier(&self, ptr: NonNull<u8>) -> ProcessCustomGrantIdentifier {
2668        let custom_grant_address = ptr.as_ptr() as usize;
2669        let process_memory_end = self.mem_end() as usize;
2670
2671        ProcessCustomGrantIdentifier {
2672            offset: process_memory_end - custom_grant_address,
2673        }
2674    }
2675
2676    /// Use a `ProcessCustomGrantIdentifier` to find the address of the
2677    /// custom grant.
2678    ///
2679    /// This reverses `create_custom_grant_identifier()`.
2680    fn get_custom_grant_address(&self, identifier: ProcessCustomGrantIdentifier) -> usize {
2681        let process_memory_end = self.mem_end() as usize;
2682
2683        // Subtract the offset in the identifier from the end of the process
2684        // memory to get the address of the custom grant.
2685        process_memory_end - identifier.offset
2686    }
2687
2688    /// Return the app's read and modify storage permissions from the TBF header
2689    /// if it exists.
2690    ///
2691    /// If the header does not exist then return `None`. If the header does
2692    /// exist, this returns a 5-tuple with:
2693    ///
2694    /// - `write_allowed`: bool. If this process should have write permissions.
2695    /// - `read_count`: usize. How many read IDs are valid.
2696    /// - `read_ids`: [u32]. The read IDs.
2697    /// - `modify_count`: usze. How many modify IDs are valid.
2698    /// - `modify_ids`: [u32]. The modify IDs.
2699    pub fn get_tbf_storage_permissions(&self) -> Option<(bool, usize, [u32; 8], usize, [u32; 8])> {
2700        let read_perms = self.header.get_storage_read_ids();
2701        let modify_perms = self.header.get_storage_modify_ids();
2702
2703        match (read_perms, modify_perms) {
2704            (Some((read_count, read_ids)), Some((modify_count, modify_ids))) => Some((
2705                self.header.get_storage_write_id().is_some(),
2706                read_count,
2707                read_ids,
2708                modify_count,
2709                modify_ids,
2710            )),
2711            _ => None,
2712        }
2713    }
2714
2715    /// The start address of allocated RAM for this process.
2716    fn mem_start(&self) -> *const u8 {
2717        self.memory_start
2718    }
2719
2720    /// The first address after the end of the allocated RAM for this process.
2721    fn mem_end(&self) -> *const u8 {
2722        self.memory_start.wrapping_add(self.memory_len)
2723    }
2724
2725    /// The start address of the flash region allocated for this process.
2726    fn flash_start(&self) -> *const u8 {
2727        self.flash.as_ptr()
2728    }
2729
2730    /// Get the first address of process's flash that isn't protected by the
2731    /// kernel. The protected range of flash contains the TBF header and
2732    /// potentially other state the kernel is storing on behalf of the process,
2733    /// and cannot be edited by the process.
2734    fn flash_non_protected_start(&self) -> usize {
2735        (self.flash.as_ptr() as usize) + self.header.get_protected_size() as usize
2736    }
2737
2738    /// The first address after the end of the flash region allocated for this
2739    /// process.
2740    fn flash_end(&self) -> usize {
2741        self.flash.as_ptr().addr().wrapping_add(self.flash.len())
2742    }
2743
2744    /// The lowest address of the grant region for the process.
2745    fn kernel_memory_break(&self) -> *const u8 {
2746        self.kernel_memory_break.get()
2747    }
2748
2749    /// Return the highest address the process has access to, or the current
2750    /// process memory brk.
2751    fn app_memory_break(&self) -> *const u8 {
2752        self.app_break.get()
2753    }
2754}