1use sel4_config::{sel4_cfg, sel4_cfg_enum, sel4_cfg_if, sel4_cfg_wrap_match};
8
9use crate::{
10 CapTypeForFrameObject, CapTypeForFrameObjectOfFixedSize, CapTypeForTranslationTableObject,
11 ObjectBlueprint, ObjectBlueprintX64, ObjectBlueprintX86, cap_type,
12 const_helpers::u32_into_usize, sys,
13};
14
15#[sel4_cfg_enum]
17#[derive(Copy, Clone, Debug, PartialEq, Eq)]
18pub enum FrameObjectType {
19 _4k,
20 LargePage,
21 #[sel4_cfg(HUGE_PAGE)]
22 HugePage,
23}
24
25impl FrameObjectType {
26 pub const GRANULE: Self = Self::_4k;
27
28 pub const fn blueprint(self) -> ObjectBlueprint {
29 sel4_cfg_wrap_match! {
30 match self {
31 Self::_4k => ObjectBlueprint::Arch(ObjectBlueprintX86::_4k),
32 Self::LargePage => ObjectBlueprint::Arch(ObjectBlueprintX86::LargePage),
33 #[sel4_cfg(HUGE_PAGE)]
34 Self::HugePage => {
35 ObjectBlueprint::Arch(ObjectBlueprintX86::SeL4Arch(ObjectBlueprintX64::HugePage))
36 }
37 }
38 }
39 }
40
41 pub const fn from_bits(bits: usize) -> Option<Self> {
42 Some(sel4_cfg_wrap_match! {
43 match bits {
44 Self::_4K_BITS => Self::_4k,
45 Self::LARGE_PAGE_BITS => Self::LargePage,
46 #[sel4_cfg(HUGE_PAGE)]
47 Self::HUGE_PAGE_BITS => Self::HugePage,
48 _ => return None,
49 }
50 })
51 }
52
53 pub const _4K_BITS: usize = Self::_4k.bits();
55 pub const LARGE_PAGE_BITS: usize = Self::LargePage.bits();
56
57 #[sel4_cfg(HUGE_PAGE)]
58 pub const HUGE_PAGE_BITS: usize = Self::HugePage.bits();
59}
60
61impl CapTypeForFrameObject for cap_type::_4k {}
62
63impl CapTypeForFrameObjectOfFixedSize for cap_type::_4k {
64 const FRAME_OBJECT_TYPE: FrameObjectType = FrameObjectType::_4k;
65}
66
67impl CapTypeForFrameObject for cap_type::LargePage {}
68
69impl CapTypeForFrameObjectOfFixedSize for cap_type::LargePage {
70 const FRAME_OBJECT_TYPE: FrameObjectType = FrameObjectType::LargePage;
71}
72
73sel4_cfg_if! {
74 if #[sel4_cfg(HUGE_PAGE)] {
75 impl CapTypeForFrameObject for cap_type::HugePage {}
76
77 impl CapTypeForFrameObjectOfFixedSize for cap_type::HugePage {
78 const FRAME_OBJECT_TYPE: FrameObjectType = FrameObjectType::HugePage;
79 }
80 }
81}
82
83#[sel4_cfg_enum]
87#[derive(Copy, Clone, Debug, PartialEq, Eq)]
88pub enum TranslationTableObjectType {
89 PML4,
90 PDPT,
91 PageDirectory,
92 PageTable,
93 #[sel4_cfg(VTX)]
94 EPTPML4,
95 #[sel4_cfg(VTX)]
96 EPTPDPT,
97 #[sel4_cfg(VTX)]
98 EPTPageDirectory,
99 #[sel4_cfg(VTX)]
100 EPTPageTable,
101 #[sel4_cfg(IOMMU)]
102 IOPageTable,
103}
104
105impl TranslationTableObjectType {
106 pub const fn blueprint(&self) -> ObjectBlueprint {
107 sel4_cfg_wrap_match! {
108 match self {
109 Self::PML4 => {
110 ObjectBlueprint::Arch(ObjectBlueprintX86::SeL4Arch(ObjectBlueprintX64::PML4))
111 }
112 Self::PDPT => {
113 ObjectBlueprint::Arch(ObjectBlueprintX86::SeL4Arch(ObjectBlueprintX64::PDPT))
114 }
115 Self::PageDirectory => ObjectBlueprint::Arch(ObjectBlueprintX86::PageDirectory),
116 Self::PageTable => ObjectBlueprint::Arch(ObjectBlueprintX86::PageTable),
117 #[sel4_cfg(VTX)]
118 Self::EPTPML4 => {
119 ObjectBlueprint::Arch(ObjectBlueprintX86::SeL4Arch(ObjectBlueprintX64::EPTPML4))
120 }
121 #[sel4_cfg(VTX)]
122 Self::EPTPDPT => {
123 ObjectBlueprint::Arch(ObjectBlueprintX86::SeL4Arch(ObjectBlueprintX64::EPTPDPT))
124 }
125 #[sel4_cfg(VTX)]
126 Self::EPTPageDirectory => ObjectBlueprint::Arch(ObjectBlueprintX86::EPTPageDirectory),
127 #[sel4_cfg(VTX)]
128 Self::EPTPageTable => ObjectBlueprint::Arch(ObjectBlueprintX86::EPTPageTable),
129 #[sel4_cfg(IOMMU)]
130 Self::IOPageTable => ObjectBlueprint::Arch(ObjectBlueprintX86::IOPageTable),
131 }
132 }
133 }
134
135 pub const fn index_bits(&self) -> usize {
136 sel4_cfg_wrap_match! {
137 match self {
138 Self::PML4 => u32_into_usize(sys::seL4_PML4IndexBits),
139 Self::PDPT => u32_into_usize(sys::seL4_PDPTIndexBits),
140 Self::PageDirectory => u32_into_usize(sys::seL4_PageDirIndexBits),
141 Self::PageTable => u32_into_usize(sys::seL4_PageTableIndexBits),
142 #[sel4_cfg(VTX)]
143 Self::EPTPML4 => u32_into_usize(sys::seL4_X86_EPTPML4IndexBits),
144 #[sel4_cfg(VTX)]
145 Self::EPTPDPT => u32_into_usize(sys::seL4_X86_EPTPDPTIndexBits),
146 #[sel4_cfg(VTX)]
147 Self::EPTPageDirectory => u32_into_usize(sys::seL4_X86_EPTPDIndexBits),
148 #[sel4_cfg(VTX)]
149 Self::EPTPageTable => u32_into_usize(sys::seL4_X86_EPTPTIndexBits),
150 #[sel4_cfg(IOMMU)]
151 Self::IOPageTable => u32_into_usize(sys::seL4_IOPageTableIndexBits),
152 }
153 }
154 }
155
156 pub const fn from_level(level: usize) -> Option<Self> {
157 Some(match level {
158 0 => Self::PML4,
159 1 => Self::PDPT,
160 2 => Self::PageDirectory,
161 3 => Self::PageTable,
162 _ => return None,
163 })
164 }
165
166 #[sel4_cfg(VTX)]
167 pub const fn from_level_ept(level: usize) -> Option<Self> {
168 Some(match level {
169 0 => Self::EPTPML4,
170 1 => Self::EPTPDPT,
171 2 => Self::EPTPageDirectory,
172 3 => Self::EPTPageTable,
173 _ => return None,
174 })
175 }
176
177 #[sel4_cfg(IOMMU)]
178 pub const fn from_level_io_page_table(_level: usize) -> Option<Self> {
179 Some(Self::IOPageTable)
180 }
181}
182
183impl CapTypeForTranslationTableObject for cap_type::PML4 {
184 const TRANSLATION_TABLE_OBJECT_TYPE: TranslationTableObjectType =
185 TranslationTableObjectType::PML4;
186}
187
188impl CapTypeForTranslationTableObject for cap_type::PDPT {
189 const TRANSLATION_TABLE_OBJECT_TYPE: TranslationTableObjectType =
190 TranslationTableObjectType::PDPT;
191}
192
193impl CapTypeForTranslationTableObject for cap_type::PageDirectory {
194 const TRANSLATION_TABLE_OBJECT_TYPE: TranslationTableObjectType =
195 TranslationTableObjectType::PageDirectory;
196}
197
198impl CapTypeForTranslationTableObject for cap_type::PageTable {
199 const TRANSLATION_TABLE_OBJECT_TYPE: TranslationTableObjectType =
200 TranslationTableObjectType::PageTable;
201}
202
203#[sel4_cfg(IOMMU)]
204impl CapTypeForTranslationTableObject for cap_type::IOPageTable {
205 const TRANSLATION_TABLE_OBJECT_TYPE: TranslationTableObjectType =
206 TranslationTableObjectType::IOPageTable;
207}
208
209pub mod vspace_levels {
210 pub const NUM_LEVELS: usize = 4;
211
212 pub const HIGHEST_LEVEL_WITH_PAGE_ENTRIES: usize = NUM_LEVELS - 3;
213}
214
215#[sel4_cfg(all(ARCH_X86_64, IOMMU))]
216pub mod io_space {
217 use super::sys;
218 use crate::{Word, newtype_methods};
219
220 use sel4_sys::seL4_X86_IOSpace_CapData;
221 #[derive(Debug, Clone, PartialEq, Eq)]
223 pub struct IOSpaceCapData(sys::seL4_X86_IOSpace_CapData);
224
225 impl IOSpaceCapData {
226 newtype_methods!(pub sys::seL4_X86_IOSpace_CapData);
227
228 pub fn new(domain_id: u64, pci_bus: u64, pci_dev: u64, pci_fun: u64) -> Self {
229 Self::from_inner(seL4_X86_IOSpace_CapData::new(
230 domain_id, pci_bus, pci_dev, pci_fun,
231 ))
232 }
233
234 pub fn into_word(self) -> Word {
235 let [word] = self.into_inner().0.into_inner();
236 word
237 }
238 }
239
240 impl From<IOSpaceCapData> for Word {
241 fn from(cap_data: IOSpaceCapData) -> Self {
242 cap_data.into_word()
243 }
244 }
245
246 pub mod levels {
247 use super::super::{FrameObjectType, TranslationTableObjectType};
248
249 fn span_bits(num_levels: usize, level: usize) -> usize {
251 assert!(level < num_levels);
252 (level..num_levels)
253 .map(|level| {
254 TranslationTableObjectType::from_level_io_page_table(level)
255 .unwrap()
256 .index_bits()
257 })
258 .sum::<usize>()
259 + FrameObjectType::GRANULE.bits()
260 }
261
262 pub fn step_bits(num_levels: usize, level: usize) -> usize {
263 span_bits(num_levels, level)
264 - TranslationTableObjectType::from_level_io_page_table(level)
265 .unwrap()
266 .index_bits()
267 }
268 }
269}