sel4/
init_thread.rs

1//
2// Copyright 2024, Colias Group, LLC
3//
4// SPDX-License-Identifier: MIT
5//
6
7//! Items that are applicable within the context of the root task's initial thread's CSpace.
8
9use core::marker::PhantomData;
10use core::ops::Range;
11
12use sel4_config::sel4_cfg;
13
14use crate::{
15    cap_type,
16    const_helpers::{u32_into_usize, usize_into_word, word_into_usize},
17    sys, CPtr, CPtrBits, Cap, CapType,
18};
19
20/// The index of a slot in the initial thread's root CNode.
21#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
22pub struct Slot<T: CapType = cap_type::Unspecified> {
23    index: usize,
24    _phantom: PhantomData<T>,
25}
26
27impl<T: CapType> Slot<T> {
28    const fn from_sys(slot: u32) -> Self {
29        Self::from_index(u32_into_usize(slot))
30    }
31
32    pub const fn from_index(index: usize) -> Self {
33        Self {
34            index,
35            _phantom: PhantomData,
36        }
37    }
38
39    pub const fn index(&self) -> usize {
40        self.index
41    }
42
43    pub const fn cptr_bits(&self) -> CPtrBits {
44        usize_into_word(self.index)
45    }
46
47    pub const fn cptr(&self) -> CPtr {
48        CPtr::from_bits(self.cptr_bits())
49    }
50
51    pub const fn cap(&self) -> Cap<T> {
52        self.cptr().cast()
53    }
54
55    pub const fn cast<T1: CapType>(&self) -> Slot<T1> {
56        Slot::from_index(self.index)
57    }
58
59    pub const fn upcast(&self) -> Slot {
60        self.cast()
61    }
62}
63
64impl Slot {
65    pub const fn downcast<T: CapType>(&self) -> Slot<T> {
66        self.cast()
67    }
68}
69
70/// Corresponds to `seL4_SlotRegion`.
71#[derive(Debug, Clone, Eq, PartialEq)]
72pub struct SlotRegion<T: CapType> {
73    range: Range<usize>,
74    _phantom: PhantomData<T>,
75}
76
77#[allow(clippy::len_without_is_empty)]
78impl<T: CapType> SlotRegion<T> {
79    pub(crate) const fn from_range(range: Range<usize>) -> Self {
80        Self {
81            range,
82            _phantom: PhantomData,
83        }
84    }
85
86    pub(crate) const fn from_sys(sys: sys::seL4_SlotRegion) -> Self {
87        Self::from_range(word_into_usize(sys.start)..word_into_usize(sys.end))
88    }
89
90    pub const fn start(&self) -> usize {
91        self.range.start
92    }
93
94    pub const fn end(&self) -> usize {
95        self.range.end
96    }
97
98    pub const fn range(&self) -> Range<usize> {
99        self.start()..self.end()
100    }
101
102    pub fn len(&self) -> usize {
103        self.range.len()
104    }
105
106    pub fn index(&self, i: usize) -> Slot<T> {
107        assert!(i < self.len());
108        Slot::from_index(self.range.start + i)
109    }
110}
111
112/// Initial CSpace slot constants corresponding to `seL4_Cap*`.
113pub mod slot {
114    use super::{cap_type, sel4_cfg, sys, Slot};
115
116    macro_rules! mk {
117        [
118            $(
119                $(#[$outer:meta])*
120                ($name:ident, $cap_type:ident, $sys_name:ident),
121            )*
122        ] => {
123            $(
124                $(#[$outer])*
125                #[doc = "Corresponds to `"]
126                #[doc = stringify!($sys_name)]
127                #[doc = "`."]
128                pub const $name: Slot<cap_type::$cap_type> = Slot::from_sys(sys::seL4_RootCNodeCapSlots::$sys_name);
129            )*
130        };
131    }
132
133    mk![
134        (NULL, Null, seL4_CapNull),
135        (TCB, Tcb, seL4_CapInitThreadTCB),
136        (CNODE, CNode, seL4_CapInitThreadCNode),
137        (VSPACE, VSpace, seL4_CapInitThreadVSpace),
138        (IRQ_CONTROL, IrqControl, seL4_CapIRQControl),
139        (ASID_CONTROL, AsidControl, seL4_CapASIDControl),
140        (ASID_POOL, AsidPool, seL4_CapInitThreadASIDPool),
141        #[sel4_cfg(not(ARCH_X86_64))]
142        (IO_PORT_CONTROL, Null, seL4_CapIOPortControl),
143        #[sel4_cfg(ARCH_X86_64)]
144        (IO_PORT_CONTROL, IOPortControl, seL4_CapIOPortControl),
145        #[cfg(any())] // TODO
146        (IO_SPACE, Null, seL4_CapIOSpace),
147        (BOOT_INFO_FRAME, Granule, seL4_CapBootInfoFrame),
148        (IPC_BUFFER, Granule, seL4_CapInitThreadIPCBuffer),
149        #[cfg(any())] // TODO
150        (DOMAIN, Null, seL4_CapDomain),
151        #[cfg(any())] // TODO
152        (SMMU_SID_CONTROL, Null, seL4_CapSMMUSIDControl),
153        #[cfg(any())] // TODO
154        (SMMU_CB_CONTROL, Null, seL4_CapSMMUCBControl),
155        #[sel4_cfg(KERNEL_MCS)]
156        (SC, SchedControl, seL4_CapInitThreadSC),
157        #[cfg(any())] // TODO
158        (SMC, Null, seL4_CapSMC),
159    ];
160}
161
162/// Suspends the initial thread using [`slot::TCB`].
163#[cfg(feature = "state")]
164pub fn suspend_self<T>() -> T {
165    slot::TCB.cap().tcb_suspend().unwrap();
166
167    unreachable!()
168}