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