Skip to main content

sel4/arch/x86/
invocations.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: MIT
5//
6
7use sel4_config::sel4_cfg;
8
9use crate::{
10    AbsoluteCPtr, Cap, CapRights, CapTypeForFrameObject, Error, InvocationContext, Result,
11    TranslationTableObjectType, VmAttributes, Word, cap::*, cap_type, sel4_cfg_wrap_match,
12};
13
14#[sel4_cfg(VTX)]
15impl<C: InvocationContext> VCpu<C> {
16    /// Corresponds to `seL4_X86_VCPU_SetTCB`.
17    pub fn vcpu_set_tcb(self, tcb: Tcb) -> Result<()> {
18        Error::wrap(self.invoke(|cptr, ipc_buffer| {
19            ipc_buffer
20                .inner_mut()
21                .seL4_X86_VCPU_SetTCB(cptr.bits(), tcb.bits())
22        }))
23    }
24}
25
26impl<T: CapTypeForFrameObject, C: InvocationContext> Cap<T, C> {
27    /// Corresponds to `seL4_X86_Page_Map`.
28    pub fn frame_map(
29        self,
30        vspace: VSpace,
31        vaddr: usize,
32        rights: CapRights,
33        attrs: VmAttributes,
34    ) -> Result<()> {
35        Error::wrap(self.invoke(|cptr, ipc_buffer| {
36            ipc_buffer.inner_mut().seL4_X86_Page_Map(
37                cptr.bits(),
38                vspace.bits(),
39                vaddr.try_into().unwrap(),
40                rights.into_inner(),
41                attrs.into_inner(),
42            )
43        }))
44    }
45
46    /// Corresponds to `seL4_X86_Page_MapEPT`.
47    #[sel4_cfg(VTX)]
48    pub fn ept_frame_map(
49        self,
50        eptmpl4: EPTPML4,
51        vaddr: usize,
52        rights: CapRights,
53        attrs: VmAttributes,
54    ) -> Result<()> {
55        Error::wrap(self.invoke(|cptr, ipc_buffer| {
56            ipc_buffer.inner_mut().seL4_X86_Page_MapEPT(
57                cptr.bits(),
58                eptmpl4.bits(),
59                vaddr.try_into().unwrap(),
60                rights.into_inner(),
61                attrs.into_inner(),
62            )
63        }))
64    }
65
66    #[sel4_cfg(IOMMU)]
67    pub fn io_frame_map(self, iospace: IOSpace, rights: CapRights, ioaddr: Word) -> Result<()> {
68        Error::wrap(self.invoke(|cptr, ipc_buffer| {
69            ipc_buffer.inner_mut().seL4_X86_Page_MapIO(
70                cptr.bits(),
71                iospace.bits(),
72                rights.into_inner(),
73                ioaddr,
74            )
75        }))
76    }
77
78    /// Corresponds to `seL4_X86_Page_Unmap`.
79    pub fn frame_unmap(self) -> Result<()> {
80        Error::wrap(
81            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_X86_Page_Unmap(cptr.bits())),
82        )
83    }
84
85    /// Corresponds to `seL4_X86_Page_GetAddress`.
86    pub fn frame_get_address(self) -> Result<usize> {
87        let ret = self.invoke(|cptr, ipc_buffer| {
88            ipc_buffer.inner_mut().seL4_X86_Page_GetAddress(cptr.bits())
89        });
90        match Error::from_sys(ret.error) {
91            None => Ok(ret.paddr.try_into().unwrap()),
92            Some(err) => Err(err),
93        }
94    }
95}
96
97impl<C: InvocationContext> PDPT<C> {
98    pub fn pdpt_map(self, vspace: VSpace, vaddr: usize, attr: VmAttributes) -> Result<()> {
99        Error::wrap(self.invoke(|cptr, ipc_buffer| {
100            ipc_buffer.inner_mut().seL4_X86_PDPT_Map(
101                cptr.bits(),
102                vspace.bits(),
103                vaddr.try_into().unwrap(),
104                attr.into_inner(),
105            )
106        }))
107    }
108}
109
110impl<C: InvocationContext> PageDirectory<C> {
111    pub fn page_directory_map(
112        self,
113        vspace: VSpace,
114        vaddr: usize,
115        attr: VmAttributes,
116    ) -> Result<()> {
117        Error::wrap(self.invoke(|cptr, ipc_buffer| {
118            ipc_buffer.inner_mut().seL4_X86_PageDirectory_Map(
119                cptr.bits(),
120                vspace.bits(),
121                vaddr.try_into().unwrap(),
122                attr.into_inner(),
123            )
124        }))
125    }
126}
127
128impl<C: InvocationContext> PageTable<C> {
129    pub fn page_table_map(self, vspace: VSpace, vaddr: usize, attr: VmAttributes) -> Result<()> {
130        Error::wrap(self.invoke(|cptr, ipc_buffer| {
131            ipc_buffer.inner_mut().seL4_X86_PageTable_Map(
132                cptr.bits(),
133                vspace.bits(),
134                vaddr.try_into().unwrap(),
135                attr.into_inner(),
136            )
137        }))
138    }
139}
140
141#[sel4_cfg(VTX)]
142impl<C: InvocationContext> EPTPDPT<C> {
143    pub fn eptpdpt_map(self, eptmpl4: EPTPML4, vaddr: usize, attr: VmAttributes) -> Result<()> {
144        Error::wrap(self.invoke(|cptr, ipc_buffer| {
145            ipc_buffer.inner_mut().seL4_X86_EPTPDPT_Map(
146                cptr.bits(),
147                eptmpl4.bits(),
148                vaddr.try_into().unwrap(),
149                attr.into_inner(),
150            )
151        }))
152    }
153}
154
155#[sel4_cfg(VTX)]
156impl<C: InvocationContext> EPTPageDirectory<C> {
157    pub fn ept_page_directory_map(
158        self,
159        eptmpl4: EPTPML4,
160        vaddr: usize,
161        attr: VmAttributes,
162    ) -> Result<()> {
163        Error::wrap(self.invoke(|cptr, ipc_buffer| {
164            ipc_buffer.inner_mut().seL4_X86_EPTPD_Map(
165                cptr.bits(),
166                eptmpl4.bits(),
167                vaddr.try_into().unwrap(),
168                attr.into_inner(),
169            )
170        }))
171    }
172}
173
174#[sel4_cfg(VTX)]
175impl<C: InvocationContext> EPTPageTable<C> {
176    pub fn ept_page_table_map(
177        self,
178        eptmpl4: EPTPML4,
179        vaddr: usize,
180        attr: VmAttributes,
181    ) -> Result<()> {
182        Error::wrap(self.invoke(|cptr, ipc_buffer| {
183            ipc_buffer.inner_mut().seL4_X86_EPTPT_Map(
184                cptr.bits(),
185                eptmpl4.bits(),
186                vaddr.try_into().unwrap(),
187                attr.into_inner(),
188            )
189        }))
190    }
191}
192
193#[sel4_cfg(IOMMU)]
194impl<C: InvocationContext> IOPageTable<C> {
195    pub fn io_page_table_map(self, iospace: IOSpace, ioaddr: Word) -> Result<()> {
196        Error::wrap(self.invoke(|cptr, ipc_buffer| {
197            ipc_buffer
198                .inner_mut()
199                .seL4_X86_IOPageTable_Map(cptr.bits(), iospace.bits(), ioaddr)
200        }))
201    }
202
203    pub fn io_page_table_unmap(self) -> Result<()> {
204        Error::wrap(self.invoke(|cptr, ipc_buffer| {
205            ipc_buffer
206                .inner_mut()
207                .seL4_X86_IOPageTable_Unmap(cptr.bits())
208        }))
209    }
210}
211
212impl<C: InvocationContext> Tcb<C> {
213    /// Corresponds to `seL4_TCB_SetEPTRoot`
214    #[sel4_cfg(VTX)]
215    pub fn tcb_set_ept_root(self, eptmpl4: EPTPML4) -> Result<()> {
216        Error::wrap(self.invoke(|cptr, ipc_buffer| {
217            ipc_buffer
218                .inner_mut()
219                .seL4_TCB_SetEPTRoot(cptr.bits(), eptmpl4.bits())
220        }))
221    }
222}
223
224impl<C: InvocationContext> UnspecifiedIntermediateTranslationTable<C> {
225    pub fn generic_intermediate_translation_table_map(
226        self,
227        ty: TranslationTableObjectType,
228        vspace: VSpace,
229        vaddr: usize,
230        attr: VmAttributes,
231    ) -> Result<()> {
232        sel4_cfg_wrap_match! {
233            match ty {
234                #[sel4_cfg(ARCH_X86_64)]
235                TranslationTableObjectType::PDPT => self.cast::<cap_type::PDPT>().pdpt_map(vspace, vaddr, attr),
236                TranslationTableObjectType::PageDirectory => self
237                    .cast::<cap_type::PageDirectory>()
238                    .page_directory_map(vspace, vaddr, attr),
239                TranslationTableObjectType::PageTable => self
240                    .cast::<cap_type::PageTable>()
241                    .page_table_map(vspace, vaddr, attr),
242                _ => panic!(),
243            }
244        }
245    }
246
247    #[sel4_cfg(VTX)]
248    pub fn ept_intermediate_translation_table_map(
249        self,
250        ty: TranslationTableObjectType,
251        vspace: EPTPML4,
252        vaddr: usize,
253        attr: VmAttributes,
254    ) -> Result<()> {
255        sel4_cfg_wrap_match! {
256            match ty {
257                #[sel4_cfg(ARCH_X86_64)]
258                TranslationTableObjectType::EPTPDPT => self.cast::<cap_type::EPTPDPT>().eptpdpt_map(vspace, vaddr, attr),
259                TranslationTableObjectType::EPTPageDirectory => self
260                    .cast::<cap_type::EPTPageDirectory>()
261                    .ept_page_directory_map(vspace, vaddr, attr),
262                TranslationTableObjectType::EPTPageTable => self
263                    .cast::<cap_type::EPTPageTable>()
264                    .ept_page_table_map(vspace, vaddr, attr),
265                _ => panic!(),
266            }
267        }
268    }
269}
270
271impl<C: InvocationContext> IrqControl<C> {
272    /// Corresponds to `seL4_IRQControl_GetIOAPIC`.
273    pub fn irq_control_get_ioapic(
274        self,
275        ioapic: Word,
276        pin: Word,
277        level: Word,
278        polarity: Word,
279        vector: Word,
280        dst: &AbsoluteCPtr,
281    ) -> Result<()> {
282        Error::wrap(self.invoke(|cptr, ipc_buffer| {
283            ipc_buffer.inner_mut().seL4_IRQControl_GetIOAPIC(
284                cptr.bits(),
285                dst.root().bits(),
286                dst.path().bits(),
287                dst.path().depth_for_kernel(),
288                ioapic,
289                pin,
290                level,
291                polarity,
292                vector,
293            )
294        }))
295    }
296
297    /// Corresponds to `seL4_IRQControl_GetMSI`.
298    pub fn irq_control_get_msi(
299        self,
300        pci_bus: Word,
301        pci_dev: Word,
302        pci_func: Word,
303        handle: Word,
304        vector: Word,
305        dst: &AbsoluteCPtr,
306    ) -> Result<()> {
307        Error::wrap(self.invoke(|cptr, ipc_buffer| {
308            ipc_buffer.inner_mut().seL4_IRQControl_GetMSI(
309                cptr.bits(),
310                dst.root().bits(),
311                dst.path().bits(),
312                dst.path().depth_for_kernel(),
313                pci_bus,
314                pci_dev,
315                pci_func,
316                handle,
317                vector,
318            )
319        }))
320    }
321}
322
323impl<C: InvocationContext> IOPortControl<C> {
324    /// Corresponds to `seL4_X86_IOPortControl_Issue`.
325    pub fn ioport_control_issue(
326        self,
327        first_port: Word,
328        last_port: Word,
329        dst: &AbsoluteCPtr,
330    ) -> Result<()> {
331        Error::wrap(self.invoke(|cptr, ipc_buffer| {
332            ipc_buffer.inner_mut().seL4_X86_IOPortControl_Issue(
333                cptr.bits(),
334                first_port,
335                last_port,
336                dst.root().bits(),
337                dst.path().bits(),
338                dst.path().depth_for_kernel(),
339            )
340        }))
341    }
342}
343
344impl<C: InvocationContext> AsidControl<C> {
345    /// Corresponds to `seL4_X86_ASIDControl_MakePool`.
346    pub fn asid_control_make_pool(self, untyped: Untyped, dst: &AbsoluteCPtr) -> Result<()> {
347        Error::wrap(self.invoke(|cptr, ipc_buffer| {
348            ipc_buffer.inner_mut().seL4_X86_ASIDControl_MakePool(
349                cptr.bits(),
350                untyped.bits(),
351                dst.root().bits(),
352                dst.path().bits(),
353                dst.path().depth_for_kernel(),
354            )
355        }))
356    }
357}
358
359impl<C: InvocationContext> AsidPool<C> {
360    /// Corresponds to `seL4_X86_ASIDPool_Assign`.
361    pub fn asid_pool_assign(self, vspace: VSpace) -> Result<()> {
362        Error::wrap(self.invoke(|cptr, ipc_buffer| {
363            ipc_buffer
364                .inner_mut()
365                .seL4_X86_ASIDPool_Assign(cptr.bits(), vspace.bits())
366        }))
367    }
368}