sel4_microkit/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//
// Copyright 2023, Colias Group, LLC
//
// SPDX-License-Identifier: BSD-2-Clause
//

#![no_std]
#![feature(cfg_target_thread_local)]

//! A foundation for pure-Rust [seL4 Microkit](https://github.com/seL4/microkit) protection domains.
//!
//! See the [seL4 Microkit manual](https://github.com/seL4/microkit/blob/main/docs/manual.md) for
//! non-Rust-specific documentation about the seL4 Microkit.
//!
//! See [the demo](https://github.com/seL4/rust-microkit-demo) for a concrete example of
//! this crate in action.
//!
//! This crate depends, at build time, on the libsel4 headers. It requires that either
//! `$SEL4_INCLUDE_DIRS` contains a colon-separated list of include paths for the libsel4 headers,
//! or that `$SEL4_PREFIX` is set, in which case `$SEL4_PREFIX/libsel4/include` is used.
//!
//! The `microkit` tool expects protection domain binaries to expose a few symbols. All protection
//! domains must contain the symbol `__sel4_ipc_buffer_obj`. Furthermore, for protection domains
//! with memory regions, the `microkit` tool injects the addresses of these memory regions at build
//! time by patching designated symbols. The
//! [`*-sel4-microkit{,-minimal}.json`](https://github.com/seL4/rust-sel4/tree/main/support/targets)
//! `rustc` target specs distributed as part of the [rust-sel4
//! project](https://github.com/seL4/rust-sel4) provide `__sel4_ipc_buffer_obj`, and the
//! [`memory_region_symbol`] macro provides a conveneint way to declare memory region address
//! symbols.
//!
//! Use the [`protection_domain`] macro to declare the initialization function, stack size, and,
//! optionally, heap and heap size.

#[cfg(feature = "alloc")]
extern crate alloc;

use sel4::sel4_cfg;

pub use sel4_microkit_base::*;

mod entry;
mod heap;
mod printing;

pub mod panicking;

#[sel4_cfg(PRINTING)]
pub use printing::{debug_print, debug_println};

/// Declares a function to be the the protection domain's initialization function.
///
/// For example:
///
/// ```rust
/// #[protection_domain]
/// fn init() -> impl Handler {
///     todo!()
/// }
/// ```
///
/// The initialization function have a signature of the form:
///
/// ```rust
/// fn<T: Handler>() -> T
/// ```
///
/// (See [`Handler`])
///
/// This macro takes two optional parameters, whose values can be any expression of type `usize`:
///
/// ```rust
/// #[protection_domain(
///     stack_size = <stack_size_expr: usize>,
///     heap_size = <heap_size_expr: usize>,
/// )]
/// ```
///
/// - `stack_size`: Declares the size of the protection domain's stack, in bytes. Note that this
///   includes space for thread-local storage. If absent, [`DEFAULT_STACK_SIZE`] will be used.
/// - `heap_size`: Creates a `#[global_allocator]`, backed by a static heap of the specified size.
///   If this parameter is not specified, no `#[global_allocator]` will be automatically declared,
///   and, unless one is manually declared, heap allocations will result in a link-time error.
///
/// Note that, if both parameters are provided, they must appear in the order above.
pub use sel4_microkit_macros::protection_domain;

#[doc(hidden)]
#[macro_export]
macro_rules! declare_protection_domain {
    {
        init = $init:expr $(,)?
    } => {
        $crate::_private::declare_protection_domain! {
            init = $init,
            stack_size = $crate::_private::DEFAULT_STACK_SIZE,
        }
    };
    {
        init = $init:expr,
        stack_size = $stack_size:expr $(,)?
    } => {
        $crate::_private::declare_init!($init);
        $crate::_private::declare_stack!($stack_size);
    };
    {
        init = $init:expr,
        $(stack_size = $stack_size:expr,)?
        heap_size = $heap_size:expr $(,)?
    } => {
        $crate::_private::declare_heap!($heap_size);
        $crate::_private::declare_protection_domain! {
            init = $init,
            $(stack_size = $stack_size,)?
        }
    };
}

/// The default stack size used by [`#[protection_domain]`](crate::protection_domain).
pub const DEFAULT_STACK_SIZE: usize = 1024
    * if cfg!(panic = "unwind") && cfg!(debug_assertions) {
        128
    } else {
        64
    };

// For macros
#[doc(hidden)]
pub mod _private {
    pub use sel4_runtime_common::declare_stack;

    pub use crate::heap::_private as heap;

    pub use crate::{
        declare_heap, declare_init, declare_protection_domain, entry::run_main, DEFAULT_STACK_SIZE,
    };
}