sel4/
lib.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: MIT
5//
6
7//! This crate provides straightforward, pure-Rust bindings to the [seL4
8//! API](https://sel4.systems/Info/Docs/seL4-manual-latest.pdf).
9//!
10//! Most items in this crate correspond to types, constants, and functions in `libsel4`. See the
11//! [seL4 manual](https://sel4.systems/Info/Docs/seL4-manual-latest.pdf) for more information about
12//! the seL4 concepts and `libsel4` items references in this crate's documentation.
13//!
14//! This crate's implementation is based on the lower-level [`sel4-sys`](::sel4_sys) crate, which is
15//! generated from the libsel4 headers and interface definition files.
16//!
17//! ### Features
18//!
19//! #### `"state"`
20//!
21//! Functions in the C libsel4 use the thread-local variable `__sel4_ipc_buffer` to obtain a pointer
22//! to the current thread's IPC buffer:
23//!
24//! ```C
25//! extern __thread seL4_IPCBuffer *__sel4_ipc_buffer;
26//! ```
27//!
28//! [libmicrokit](https://github.com/seL4/microkit/tree/main/libmicrokit), which does not support
29//! thread-local storage uses the following snippet to force `__sel4_ipc_buffer` to global rather
30//! than thread-local:
31//!
32//! ```C
33//! #define __thread
34//! #include <sel4/sel4.h>
35//! ```
36//!
37//! For the sake of flexibility and applicability, this crate can be configured to use no state at
38//! all. Users can opt out of state and explicitly pass around references to the active IPC buffer
39//! instead of relying on the implementation to obtain such a reference using thread-local or global
40//! state. Such a paradigm is useful in certain uncommon circumstances, but most users will benefit
41//! from the convenience of an implicit IPC buffer. The `"state"` feature, enabled by default, uses
42//! state to allow one to make seL4 API calls without having to explicitly specify an IPC buffer.
43//!
44//! For the sake of interoperability with C, the state looks something like: `static mut
45//! __sel4_ipc_buffer: *mut IpcBuffer`. If the `"state-exposed"` feature is enabled, it is exposed
46//! with `#![no_mangle]`. If the `"state-extern"` feature is enabled, it is wrapped in an `extern
47//! "C"` block. Whether it is thread-local is determined by the following pseudocode:
48//!
49//! ```rust
50//! cfg_if! {
51//!     if #[cfg(all(any(target_thread_local, feature = "tls"), not(feature = "non-thread-local-state")))] {
52//!         // thread-local
53//!     } else if #[cfg(not(feature = "thread-local-state"))] {
54//!         // not thread-local
55//!     } else {
56//!         compile_error!(r#"invalid configuration"#);
57//!     }
58//! }
59//! ```
60//!
61//! The non-thread-local configuration should only be used in cases where the language runtime does
62//! not support thread-local storage. In those cases without thread-local storage where this crate
63//! will only ever run in a single thread, use the `"single-threaded"` feature to enable a more
64//! efficient implementation. Note that enabling the `"single-threaded"` feature in a case where
65//! this crate runs in more than one thread is unsafe.
66//!
67//! At the API level, the `"state"` feature causes [`NoExplicitInvocationContext`] to be an alias
68//! for [`ImplicitInvocationContext`], which implements [`InvocationContext`] by accessing the
69//! thread-local pointer to an IPC buffer. When the `"state"` feature is not enabled,
70//! [`NoExplicitInvocationContext`] is an alias for [`NoInvocationContext`], which does not
71//! implement [`InvocationContext`]. The thread-local IPC buffer pointer is modified and accessed by
72//! [`set_ipc_buffer`], [`with_ipc_buffer`], and [`with_ipc_buffer_mut`]. The lower-level
73//! [`try_with_ipc_buffer_slot`] and [`try_with_ipc_buffer_slot_mut`] are provided as well.
74//!
75//! ### Building
76//!
77//! This crate and its dependencies depend, at build time, on the libsel4 headers. The location of
78//! these headers is provided to this crate at build time by environment variables. If
79//! `SEL4_INCLUDE_DIRS` is set, then its value is interpreted as a colon-separated list of include
80//! paths for the libsel4 headers. Otherwise, if `SEL4_PREFIX` is set, then
81//! `$SEL4_PREFIX/libsel4/include` is used.
82
83#![no_std]
84#![feature(cfg_target_thread_local)]
85#![feature(thread_local)]
86#![allow(clippy::unit_arg)]
87
88pub use sel4_config::{
89    self as config, sel4_cfg, sel4_cfg_attr, sel4_cfg_bool, sel4_cfg_enum, sel4_cfg_if,
90    sel4_cfg_match, sel4_cfg_str, sel4_cfg_struct, sel4_cfg_usize, sel4_cfg_word,
91    sel4_cfg_wrap_match,
92};
93
94pub use sel4_sys as sys;
95
96mod arch;
97mod bootinfo;
98mod cap_rights;
99mod cnode_cap_data;
100mod const_helpers;
101mod cptr;
102mod error;
103mod fault;
104mod helper_macros;
105mod invocation_context;
106mod invocations;
107mod ipc_buffer;
108mod message_info;
109mod object;
110mod reply_authority;
111mod syscalls;
112mod vspace;
113
114pub mod init_thread;
115
116pub use bootinfo::{
117    BootInfo, BootInfoExtra, BootInfoExtraId, BootInfoExtraIter, BootInfoPtr, UntypedDesc,
118};
119pub use cap_rights::{CapRights, CapRightsBuilder};
120pub use cnode_cap_data::CNodeCapData;
121pub use cptr::{
122    cap, cap_type, AbsoluteCPtr, CPtr, CPtrBits, CPtrWithDepth, Cap, CapType, HasCPtrWithDepth,
123};
124pub use error::{Error, Result};
125pub use fault::*;
126pub use invocation_context::{InvocationContext, NoExplicitInvocationContext, NoInvocationContext};
127pub use ipc_buffer::IpcBuffer;
128pub use message_info::{MessageInfo, MessageInfoBuilder};
129pub use object::{
130    CapTypeForObject, CapTypeForObjectOfFixedSize, CapTypeForObjectOfVariableSize, ObjectBlueprint,
131    ObjectType,
132};
133pub use reply_authority::{ConveysReplyAuthority, ReplyAuthority};
134pub use syscalls::{
135    r#yield, Badge, CallWithMRs, FastMessages, IpcCapType, RecvWithMRs, NUM_MESSAGE_REGISTERS,
136};
137pub use vspace::{
138    vspace_levels, CapTypeForFrameObject, CapTypeForFrameObjectOfFixedSize,
139    CapTypeForTranslationTableObject,
140};
141
142sel4_cfg_if! {
143    if #[sel4_cfg(KERNEL_MCS)] {
144        pub use invocations::Time;
145    } else {
146        pub use syscalls::reply;
147        pub use reply_authority::ImplicitReplyAuthority;
148    }
149}
150
151#[sel4_cfg(SET_TLS_BASE_SELF)]
152pub use syscalls::set_tls_base;
153
154pub use arch::top_level::*;
155
156pub(crate) use helper_macros::{
157    declare_cap_alias, declare_cap_type, declare_cap_type_for_object,
158    declare_cap_type_for_object_of_fixed_size, declare_cap_type_for_object_of_variable_size,
159    declare_fault_newtype, newtype_methods,
160};
161
162sel4_cfg_if! {
163    if #[sel4_cfg(PRINTING)] {
164        mod printing;
165
166        pub use printing::{DebugWrite, debug_put_char};
167    }
168}
169
170sel4_cfg_if! {
171    if #[sel4_cfg(DEBUG_BUILD)] {
172        mod debug;
173
174        pub use debug::debug_snapshot;
175    }
176}
177
178sel4_cfg_if! {
179    if #[sel4_cfg(ENABLE_BENCHMARKS)] {
180        mod benchmark;
181
182        pub use benchmark::{
183            benchmark_reset_log,
184            benchmark_finalize_log,
185            benchmark_set_log_buffer,
186        };
187
188        sel4_cfg_if! {
189            if #[sel4_cfg(BENCHMARK_TRACK_UTILISATION)] {
190                pub use benchmark::{
191                    benchmark_get_thread_utilisation,
192                    benchmark_reset_thread_utilisation,
193                };
194
195                #[sel4_cfg(DEBUG_BUILD)]
196                pub use benchmark::{
197                    benchmark_dump_all_thread_utilisation,
198                    benchmark_reset_all_thread_utilisation,
199                };
200            }
201        }
202    }
203}
204
205#[cfg(feature = "state")]
206mod state;
207
208#[cfg(feature = "state")]
209pub use state::{
210    ipc_buffer_is_thread_local, set_ipc_buffer, try_with_ipc_buffer_slot,
211    try_with_ipc_buffer_slot_mut, with_ipc_buffer, with_ipc_buffer_mut, ImplicitInvocationContext,
212};
213
214/// Corresponds to `seL4_Word`.
215pub type Word = sys::seL4_Word;
216
217/// The size of [`Word`] in bits.
218pub const WORD_SIZE: usize = sel4_cfg_usize!(WORD_SIZE);
219
220#[doc(hidden)]
221pub mod _private {
222    #[sel4_config::sel4_cfg(PRINTING)]
223    pub use super::printing::_private as printing;
224}