kernel/
config.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//! Data structure for storing compile-time configuration options in the kernel.
6//!
7//! The rationale for configuration based on a `const` object is twofold.
8//!
9//! - In theory, Cargo features could be used for boolean-based configuration.
10//!   However, these features are generally error-prone for non-trivial use
11//!   cases. First, they are globally enabled as long as a dependency
12//!   relationship requires a feature (even for other dependency relationships
13//!   that do not want the feature). Second, code gated by a non-enabled feature
14//!   isn't even type-checked by the compiler, and therefore we can end up with
15//!   broken features due to refactoring code (if these features aren't tested
16//!   during the refactoring), or to incompatible feature combinations.
17//!
18//! - Cargo features can only contain bits. On the other hand, a constant value
19//!   can contain arbitrary types, which allow configuration based on integers,
20//!   strings, or even more complex values.
21//!
22//! With a typed `const` configuration, all code paths are type-checked by the
23//! compiler - even those that end up disabled - which greatly reduces the risks
24//! of breaking a feature or combination of features because they are disabled
25//! in tests.
26//!
27//! In the meantime, after type-checking, the compiler can optimize away dead
28//! code by folding constants throughout the code, so for example a boolean
29//! condition used in an `if` block will in principle have a zero cost on the
30//! resulting binary - as if a Cargo feature was used instead. Some simple
31//! experiments on generated Tock code have confirmed this zero cost in
32//! practice.
33
34/// Data structure holding compile-time configuration options.
35///
36/// To change the configuration, modify the relevant values in the `CONFIG`
37/// constant object defined at the end of this file.
38pub(crate) struct Config {
39    /// Whether the kernel should trace syscalls to the debug output.
40    ///
41    /// If enabled, the kernel will print a message in the debug output for each
42    /// system call and upcall, with details including the application ID, and
43    /// system call or upcall parameters.
44    pub(crate) trace_syscalls: bool,
45
46    /// Whether the kernel should show debugging output when loading processes.
47    ///
48    /// If enabled, the kernel will show from which addresses processes are
49    /// loaded in flash and into which SRAM addresses. This can be useful to
50    /// debug whether the kernel could successfully load processes, and whether
51    /// the allocated SRAM is as expected.
52    pub(crate) debug_load_processes: bool,
53
54    /// Whether the kernel should output additional debug information on panics.
55    ///
56    /// If enabled, the kernel will include implementations of
57    /// `Process::print_full_process()` and `Process::print_memory_map()` that
58    /// display the process's state in a human-readable form.
59    // This config option is intended to allow for smaller kernel builds (in
60    // terms of code size) where printing code is removed from the kernel
61    // binary. Ideally, the compiler would automatically remove
62    // printing/debugging functions if they are never called, but due to
63    // limitations in Rust (as of Sep 2021) that does not happen if the
64    // functions are part of a trait (see
65    // https://github.com/tock/tock/issues/2594).
66    //
67    // Attempts to separate the printing/debugging code from the Process trait
68    // have only been moderately successful (see
69    // https://github.com/tock/tock/pull/2826 and
70    // https://github.com/tock/tock/pull/2759). Until a more complete solution
71    // is identified, using configuration constants is the most effective
72    // option.
73    pub(crate) debug_panics: bool,
74
75    /// Whether the kernbel should output debug information when it is checking
76    /// the cryptographic credentials of a userspace process. If enabled, the
77    /// kernel will show which footers were found and why processes were started
78    /// or not.
79    // This config option is intended to provide some visibility into process
80    // credentials checking, e.g., whether elf2tab and tockloader are generating
81    // properly formatted footers.
82    pub(crate) debug_process_credentials: bool,
83}
84
85/// A unique instance of `Config` where compile-time configuration options are
86/// defined. These options are available in the kernel crate to be used for
87/// relevant configuration. Notably, this is the only location in the Tock
88/// kernel where we permit `#[cfg(x)]` to be used to configure code based on
89/// Cargo features.
90pub(crate) const CONFIG: Config = Config {
91    trace_syscalls: cfg!(feature = "trace_syscalls"),
92    debug_load_processes: cfg!(feature = "debug_load_processes"),
93    debug_panics: !cfg!(feature = "no_debug_panics"),
94    debug_process_credentials: cfg!(feature = "debug_process_credentials"),
95};