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    /// Corresponds to `seL4_X86_Page_Unmap`.
67    pub fn frame_unmap(self) -> Result<()> {
68        Error::wrap(
69            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_X86_Page_Unmap(cptr.bits())),
70        )
71    }
72
73    /// Corresponds to `seL4_X86_Page_GetAddress`.
74    pub fn frame_get_address(self) -> Result<usize> {
75        let ret = self.invoke(|cptr, ipc_buffer| {
76            ipc_buffer.inner_mut().seL4_X86_Page_GetAddress(cptr.bits())
77        });
78        match Error::from_sys(ret.error) {
79            None => Ok(ret.paddr.try_into().unwrap()),
80            Some(err) => Err(err),
81        }
82    }
83}
84
85impl<C: InvocationContext> PDPT<C> {
86    pub fn pdpt_map(self, vspace: VSpace, vaddr: usize, attr: VmAttributes) -> Result<()> {
87        Error::wrap(self.invoke(|cptr, ipc_buffer| {
88            ipc_buffer.inner_mut().seL4_X86_PDPT_Map(
89                cptr.bits(),
90                vspace.bits(),
91                vaddr.try_into().unwrap(),
92                attr.into_inner(),
93            )
94        }))
95    }
96}
97
98impl<C: InvocationContext> PageDirectory<C> {
99    pub fn page_directory_map(
100        self,
101        vspace: VSpace,
102        vaddr: usize,
103        attr: VmAttributes,
104    ) -> Result<()> {
105        Error::wrap(self.invoke(|cptr, ipc_buffer| {
106            ipc_buffer.inner_mut().seL4_X86_PageDirectory_Map(
107                cptr.bits(),
108                vspace.bits(),
109                vaddr.try_into().unwrap(),
110                attr.into_inner(),
111            )
112        }))
113    }
114}
115
116impl<C: InvocationContext> PageTable<C> {
117    pub fn page_table_map(self, vspace: VSpace, vaddr: usize, attr: VmAttributes) -> Result<()> {
118        Error::wrap(self.invoke(|cptr, ipc_buffer| {
119            ipc_buffer.inner_mut().seL4_X86_PageTable_Map(
120                cptr.bits(),
121                vspace.bits(),
122                vaddr.try_into().unwrap(),
123                attr.into_inner(),
124            )
125        }))
126    }
127}
128
129#[sel4_cfg(VTX)]
130impl<C: InvocationContext> EPTPDPT<C> {
131    pub fn eptpdpt_map(self, eptmpl4: EPTPML4, vaddr: usize, attr: VmAttributes) -> Result<()> {
132        Error::wrap(self.invoke(|cptr, ipc_buffer| {
133            ipc_buffer.inner_mut().seL4_X86_EPTPDPT_Map(
134                cptr.bits(),
135                eptmpl4.bits(),
136                vaddr.try_into().unwrap(),
137                attr.into_inner(),
138            )
139        }))
140    }
141}
142
143#[sel4_cfg(VTX)]
144impl<C: InvocationContext> EPTPageDirectory<C> {
145    pub fn ept_page_directory_map(
146        self,
147        eptmpl4: EPTPML4,
148        vaddr: usize,
149        attr: VmAttributes,
150    ) -> Result<()> {
151        Error::wrap(self.invoke(|cptr, ipc_buffer| {
152            ipc_buffer.inner_mut().seL4_X86_EPTPD_Map(
153                cptr.bits(),
154                eptmpl4.bits(),
155                vaddr.try_into().unwrap(),
156                attr.into_inner(),
157            )
158        }))
159    }
160}
161
162#[sel4_cfg(VTX)]
163impl<C: InvocationContext> EPTPageTable<C> {
164    pub fn ept_page_table_map(
165        self,
166        eptmpl4: EPTPML4,
167        vaddr: usize,
168        attr: VmAttributes,
169    ) -> Result<()> {
170        Error::wrap(self.invoke(|cptr, ipc_buffer| {
171            ipc_buffer.inner_mut().seL4_X86_EPTPT_Map(
172                cptr.bits(),
173                eptmpl4.bits(),
174                vaddr.try_into().unwrap(),
175                attr.into_inner(),
176            )
177        }))
178    }
179}
180
181impl<C: InvocationContext> Tcb<C> {
182    /// Corresponds to `seL4_TCB_SetEPTRoot`
183    #[sel4_cfg(VTX)]
184    pub fn tcb_set_ept_root(self, eptmpl4: EPTPML4) -> Result<()> {
185        Error::wrap(self.invoke(|cptr, ipc_buffer| {
186            ipc_buffer
187                .inner_mut()
188                .seL4_TCB_SetEPTRoot(cptr.bits(), eptmpl4.bits())
189        }))
190    }
191}
192
193impl<C: InvocationContext> UnspecifiedIntermediateTranslationTable<C> {
194    pub fn generic_intermediate_translation_table_map(
195        self,
196        ty: TranslationTableObjectType,
197        vspace: VSpace,
198        vaddr: usize,
199        attr: VmAttributes,
200    ) -> Result<()> {
201        sel4_cfg_wrap_match! {
202            match ty {
203                #[sel4_cfg(ARCH_X86_64)]
204                TranslationTableObjectType::PDPT => self.cast::<cap_type::PDPT>().pdpt_map(vspace, vaddr, attr),
205                TranslationTableObjectType::PageDirectory => self
206                    .cast::<cap_type::PageDirectory>()
207                    .page_directory_map(vspace, vaddr, attr),
208                TranslationTableObjectType::PageTable => self
209                    .cast::<cap_type::PageTable>()
210                    .page_table_map(vspace, vaddr, attr),
211                _ => panic!(),
212            }
213        }
214    }
215
216    #[sel4_cfg(VTX)]
217    pub fn ept_intermediate_translation_table_map(
218        self,
219        ty: TranslationTableObjectType,
220        vspace: EPTPML4,
221        vaddr: usize,
222        attr: VmAttributes,
223    ) -> Result<()> {
224        sel4_cfg_wrap_match! {
225            match ty {
226                #[sel4_cfg(ARCH_X86_64)]
227                TranslationTableObjectType::EPTPDPT => self.cast::<cap_type::EPTPDPT>().eptpdpt_map(vspace, vaddr, attr),
228                TranslationTableObjectType::EPTPageDirectory => self
229                    .cast::<cap_type::EPTPageDirectory>()
230                    .ept_page_directory_map(vspace, vaddr, attr),
231                TranslationTableObjectType::EPTPageTable => self
232                    .cast::<cap_type::EPTPageTable>()
233                    .ept_page_table_map(vspace, vaddr, attr),
234                _ => panic!(),
235            }
236        }
237    }
238}
239
240impl<C: InvocationContext> IrqControl<C> {
241    /// Corresponds to `seL4_IRQControl_GetIOAPIC`.
242    pub fn irq_control_get_ioapic(
243        self,
244        ioapic: Word,
245        pin: Word,
246        level: Word,
247        polarity: Word,
248        vector: Word,
249        dst: &AbsoluteCPtr,
250    ) -> Result<()> {
251        Error::wrap(self.invoke(|cptr, ipc_buffer| {
252            ipc_buffer.inner_mut().seL4_IRQControl_GetIOAPIC(
253                cptr.bits(),
254                dst.root().bits(),
255                dst.path().bits(),
256                dst.path().depth_for_kernel(),
257                ioapic,
258                pin,
259                level,
260                polarity,
261                vector,
262            )
263        }))
264    }
265
266    /// Corresponds to `seL4_IRQControl_GetMSI`.
267    pub fn irq_control_get_msi(
268        self,
269        pci_bus: Word,
270        pci_dev: Word,
271        pci_func: Word,
272        handle: Word,
273        vector: Word,
274        dst: &AbsoluteCPtr,
275    ) -> Result<()> {
276        Error::wrap(self.invoke(|cptr, ipc_buffer| {
277            ipc_buffer.inner_mut().seL4_IRQControl_GetMSI(
278                cptr.bits(),
279                dst.root().bits(),
280                dst.path().bits(),
281                dst.path().depth_for_kernel(),
282                pci_bus,
283                pci_dev,
284                pci_func,
285                handle,
286                vector,
287            )
288        }))
289    }
290}
291
292impl<C: InvocationContext> IOPortControl<C> {
293    /// Corresponds to `seL4_X86_IOPortControl_Issue`.
294    pub fn ioport_control_issue(
295        self,
296        first_port: Word,
297        last_port: Word,
298        dst: &AbsoluteCPtr,
299    ) -> Result<()> {
300        Error::wrap(self.invoke(|cptr, ipc_buffer| {
301            ipc_buffer.inner_mut().seL4_X86_IOPortControl_Issue(
302                cptr.bits(),
303                first_port,
304                last_port,
305                dst.root().bits(),
306                dst.path().bits(),
307                dst.path().depth_for_kernel(),
308            )
309        }))
310    }
311}
312
313impl<C: InvocationContext> AsidControl<C> {
314    /// Corresponds to `seL4_X86_ASIDControl_MakePool`.
315    pub fn asid_control_make_pool(self, untyped: Untyped, dst: &AbsoluteCPtr) -> Result<()> {
316        Error::wrap(self.invoke(|cptr, ipc_buffer| {
317            ipc_buffer.inner_mut().seL4_X86_ASIDControl_MakePool(
318                cptr.bits(),
319                untyped.bits(),
320                dst.root().bits(),
321                dst.path().bits(),
322                dst.path().depth_for_kernel(),
323            )
324        }))
325    }
326}
327
328impl<C: InvocationContext> AsidPool<C> {
329    /// Corresponds to `seL4_X86_ASIDPool_Assign`.
330    pub fn asid_pool_assign(self, vspace: VSpace) -> Result<()> {
331        Error::wrap(self.invoke(|cptr, ipc_buffer| {
332            ipc_buffer
333                .inner_mut()
334                .seL4_X86_ASIDPool_Assign(cptr.bits(), vspace.bits())
335        }))
336    }
337}