sel4/arch/arm/
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    cap::*, cap_type, AbsoluteCPtr, Cap, CapRights, CapTypeForFrameObject, Error,
11    InvocationContext, Result, TranslationTableObjectType, VmAttributes, Word,
12};
13
14#[sel4_cfg(ARM_HYPERVISOR_SUPPORT)]
15use crate::VCpuReg;
16
17#[sel4_cfg(ARM_HYPERVISOR_SUPPORT)]
18impl<C: InvocationContext> VCpu<C> {
19    /// Corresponds to `seL4_ARM_VCPU_SetTCB`.
20    pub fn vcpu_set_tcb(self, tcb: Tcb) -> Result<()> {
21        Error::wrap(self.invoke(|cptr, ipc_buffer| {
22            ipc_buffer
23                .inner_mut()
24                .seL4_ARM_VCPU_SetTCB(cptr.bits(), tcb.bits())
25        }))
26    }
27
28    /// Corresponds to `seL4_ARM_VCPU_ReadRegs`.
29    pub fn vcpu_read_regs(self, field: VCpuReg) -> Result<Word> {
30        let res = self.invoke(|cptr, ipc_buffer| {
31            ipc_buffer
32                .inner_mut()
33                .seL4_ARM_VCPU_ReadRegs(cptr.bits(), field.into_sys())
34        });
35        Error::or(res.error, res.value)
36    }
37
38    /// Corresponds to `seL4_ARM_VCPU_WriteRegs`.
39    pub fn vcpu_write_regs(self, field: VCpuReg, value: Word) -> Result<()> {
40        Error::wrap(self.invoke(|cptr, ipc_buffer| {
41            ipc_buffer
42                .inner_mut()
43                .seL4_ARM_VCPU_WriteRegs(cptr.bits(), field.into_sys(), value)
44        }))
45    }
46
47    /// Corresponds to `seL4_ARM_VCPU_AckVPPI`.
48    pub fn vcpu_ack_vppi(self, irq: Word) -> Result<()> {
49        Error::wrap(self.invoke(|cptr, ipc_buffer| {
50            ipc_buffer
51                .inner_mut()
52                .seL4_ARM_VCPU_AckVPPI(cptr.bits(), irq)
53        }))
54    }
55
56    /// Corresponds to `seL4_ARM_VCPU_InjectIRQ`.
57    pub fn vcpu_inject_irq(self, virq: u16, priority: u8, group: u8, index: u8) -> Result<()> {
58        Error::wrap(self.invoke(|cptr, ipc_buffer| {
59            ipc_buffer.inner_mut().seL4_ARM_VCPU_InjectIRQ(
60                cptr.bits(),
61                virq,
62                priority,
63                group,
64                index,
65            )
66        }))
67    }
68}
69
70impl<T: CapTypeForFrameObject, C: InvocationContext> Cap<T, C> {
71    /// Corresponds to `seL4_ARM_Page_Map`.
72    pub fn frame_map(
73        self,
74        vspace: VSpace,
75        vaddr: usize,
76        rights: CapRights,
77        attrs: VmAttributes,
78    ) -> Result<()> {
79        Error::wrap(self.invoke(|cptr, ipc_buffer| {
80            ipc_buffer.inner_mut().seL4_ARM_Page_Map(
81                cptr.bits(),
82                vspace.bits(),
83                vaddr.try_into().unwrap(),
84                rights.into_inner(),
85                attrs.into_inner(),
86            )
87        }))
88    }
89
90    /// Corresponds to `seL4_ARM_Page_Unmap`.
91    pub fn frame_unmap(self) -> Result<()> {
92        Error::wrap(
93            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_ARM_Page_Unmap(cptr.bits())),
94        )
95    }
96
97    /// Corresponds to `seL4_ARM_Page_GetAddress`.
98    pub fn frame_get_address(self) -> Result<usize> {
99        let ret = self.invoke(|cptr, ipc_buffer| {
100            ipc_buffer.inner_mut().seL4_ARM_Page_GetAddress(cptr.bits())
101        });
102        match Error::from_sys(ret.error) {
103            None => Ok(ret.paddr.try_into().unwrap()),
104            Some(err) => Err(err),
105        }
106    }
107}
108
109impl<C: InvocationContext> PT<C> {
110    pub fn pt_map(self, vspace: VSpace, vaddr: usize, attr: VmAttributes) -> Result<()> {
111        Error::wrap(self.invoke(|cptr, ipc_buffer| {
112            ipc_buffer.inner_mut().seL4_ARM_PageTable_Map(
113                cptr.bits(),
114                vspace.bits(),
115                vaddr.try_into().unwrap(),
116                attr.into_inner(),
117            )
118        }))
119    }
120}
121
122impl<C: InvocationContext> UnspecifiedIntermediateTranslationTable<C> {
123    pub fn generic_intermediate_translation_table_map(
124        self,
125        ty: TranslationTableObjectType,
126        vspace: VSpace,
127        vaddr: usize,
128        attr: VmAttributes,
129    ) -> Result<()> {
130        match ty {
131            TranslationTableObjectType::PT => {
132                self.cast::<cap_type::PT>().pt_map(vspace, vaddr, attr)
133            }
134            _ => panic!(),
135        }
136    }
137}
138
139// TODO structured trigger type
140impl<C: InvocationContext> IrqControl<C> {
141    /// Corresponds to `seL4_IRQControl_GetTriggerCore`.
142    #[sel4_cfg(not(MAX_NUM_NODES = "1"))]
143    pub fn irq_control_get_trigger_core(
144        self,
145        irq: Word,
146        edge_triggered: bool,
147        target: Word,
148        dst: &AbsoluteCPtr,
149    ) -> Result<()> {
150        Error::wrap(self.invoke(|cptr, ipc_buffer| {
151            ipc_buffer.inner_mut().seL4_IRQControl_GetTriggerCore(
152                cptr.bits(),
153                irq,
154                edge_triggered.into(),
155                dst.root().bits(),
156                dst.path().bits(),
157                dst.path().depth_for_kernel(),
158                target,
159            )
160        }))
161    }
162
163    /// Corresponds to `seL4_IRQControl_GetTrigger`.
164    pub fn irq_control_get_trigger(
165        self,
166        irq: Word,
167        edge_triggered: bool,
168        dst: &AbsoluteCPtr,
169    ) -> Result<()> {
170        Error::wrap(self.invoke(|cptr, ipc_buffer| {
171            ipc_buffer.inner_mut().seL4_IRQControl_GetTrigger(
172                cptr.bits(),
173                irq,
174                edge_triggered.into(),
175                dst.root().bits(),
176                dst.path().bits(),
177                dst.path().depth_for_kernel(),
178            )
179        }))
180    }
181}
182
183impl<C: InvocationContext> AsidControl<C> {
184    /// Corresponds to `seL4_ARM_ASIDControl_MakePool`.
185    pub fn asid_control_make_pool(self, untyped: Untyped, dst: &AbsoluteCPtr) -> Result<()> {
186        Error::wrap(self.invoke(|cptr, ipc_buffer| {
187            ipc_buffer.inner_mut().seL4_ARM_ASIDControl_MakePool(
188                cptr.bits(),
189                untyped.bits(),
190                dst.root().bits(),
191                dst.path().bits(),
192                dst.path().depth_for_kernel(),
193            )
194        }))
195    }
196}
197
198impl<C: InvocationContext> AsidPool<C> {
199    /// Corresponds to `seL4_ARM_ASIDPool_Assign`.
200    pub fn asid_pool_assign(self, vspace: VSpace) -> Result<()> {
201        Error::wrap(self.invoke(|cptr, ipc_buffer| {
202            ipc_buffer
203                .inner_mut()
204                .seL4_ARM_ASIDPool_Assign(cptr.bits(), vspace.bits())
205        }))
206    }
207}