sel4/
invocations.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: MIT
5//
6
7#![allow(clippy::useless_conversion)]
8
9use core::mem;
10
11use sel4_config::{sel4_cfg, sel4_cfg_if};
12
13use crate::{
14    cap::*, sys, AbsoluteCPtr, CNodeCapData, CPtr, CapRights, Error, InvocationContext,
15    ObjectBlueprint, Result, UserContext, Word,
16};
17
18#[sel4_cfg(KERNEL_MCS)]
19use crate::Badge;
20
21/// Corresponds to `seL4_Time`.
22#[sel4_cfg(KERNEL_MCS)]
23pub type Time = u64;
24
25impl<C: InvocationContext> Untyped<C> {
26    /// Corresponds to `seL4_Untyped_Retype`.
27    pub fn untyped_retype(
28        self,
29        blueprint: &ObjectBlueprint,
30        dst: &AbsoluteCPtr,
31        dst_offset: usize,
32        num_objects: usize,
33    ) -> Result<()> {
34        Error::wrap(self.invoke(|cptr, ipc_buffer| {
35            ipc_buffer.inner_mut().seL4_Untyped_Retype(
36                cptr.bits(),
37                blueprint.ty().into_sys().into(),
38                blueprint.api_size_bits().unwrap_or(0).try_into().unwrap(),
39                dst.root().bits(),
40                dst.path().bits(),
41                dst.path().depth().try_into().unwrap(),
42                dst_offset.try_into().unwrap(),
43                num_objects.try_into().unwrap(),
44            )
45        }))
46    }
47}
48
49const USER_CONTEXT_MAX_REG_COUNT: usize =
50    mem::size_of::<sys::seL4_UserContext>() / mem::size_of::<Word>();
51
52impl<C: InvocationContext> Tcb<C> {
53    /// Corresponds to `seL4_TCB_ReadRegisters`.
54    pub fn tcb_read_registers(self, suspend: bool, count: Word) -> Result<UserContext> {
55        let mut regs: UserContext = Default::default();
56        let err = self.invoke(|cptr, ipc_buffer| {
57            ipc_buffer.inner_mut().seL4_TCB_ReadRegisters(
58                cptr.bits(),
59                suspend.into(),
60                0,
61                count,
62                regs.inner_mut(),
63            )
64        });
65        Error::or(err, regs)
66    }
67
68    pub fn tcb_read_all_registers(self, suspend: bool) -> Result<UserContext> {
69        self.tcb_read_registers(suspend, USER_CONTEXT_MAX_REG_COUNT.try_into().unwrap())
70    }
71
72    /// Corresponds to `seL4_TCB_WriteRegisters`.
73    // HACK should not be mut
74    pub fn tcb_write_registers(
75        self,
76        resume: bool,
77        count: Word,
78        regs: &mut UserContext,
79    ) -> Result<()> {
80        Error::wrap(self.invoke(|cptr, ipc_buffer| {
81            ipc_buffer.inner_mut().seL4_TCB_WriteRegisters(
82                cptr.bits(),
83                resume.into(),
84                0,
85                count,
86                regs.inner_mut(),
87            )
88        }))
89    }
90
91    pub fn tcb_write_all_registers(self, resume: bool, regs: &mut UserContext) -> Result<()> {
92        self.tcb_write_registers(resume, USER_CONTEXT_MAX_REG_COUNT.try_into().unwrap(), regs)
93    }
94
95    /// Corresponds to `seL4_TCB_Resume`.
96    pub fn tcb_resume(self) -> Result<()> {
97        Error::wrap(
98            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_TCB_Resume(cptr.bits())),
99        )
100    }
101
102    /// Corresponds to `seL4_TCB_Suspend`.
103    pub fn tcb_suspend(self) -> Result<()> {
104        Error::wrap(
105            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_TCB_Suspend(cptr.bits())),
106        )
107    }
108
109    sel4_cfg_if! {
110        if #[sel4_cfg(KERNEL_MCS)] {
111            /// Corresponds to `seL4_TCB_Configure`.
112            pub fn tcb_configure(
113                self,
114                cspace_root: CNode,
115                cspace_root_data: CNodeCapData,
116                vspace_root: VSpace,
117                ipc_buffer: Word,
118                ipc_buffer_frame: Granule,
119            ) -> Result<()> {
120                Error::wrap(self.invoke(|cptr, ctx_ipc_buffer| {
121                    ctx_ipc_buffer.inner_mut().seL4_TCB_Configure(
122                        cptr.bits(),
123                        cspace_root.bits(),
124                        cspace_root_data.into_word(),
125                        vspace_root.bits(),
126                        0, /* HACK */
127                        ipc_buffer,
128                        ipc_buffer_frame.bits(),
129                    )
130                }))
131            }
132        } else {
133            /// Corresponds to `seL4_TCB_Configure`.
134            pub fn tcb_configure(
135                self,
136                fault_ep: CPtr,
137                cspace_root: CNode,
138                cspace_root_data: CNodeCapData,
139                vspace_root: VSpace,
140                ipc_buffer: Word,
141                ipc_buffer_frame: Granule,
142            ) -> Result<()> {
143                Error::wrap(self.invoke(|cptr, ctx_ipc_buffer| {
144                    ctx_ipc_buffer.inner_mut().seL4_TCB_Configure(
145                        cptr.bits(),
146                        fault_ep.bits(),
147                        cspace_root.bits(),
148                        cspace_root_data.into_word(),
149                        vspace_root.bits(),
150                        0, /* HACK */
151                        ipc_buffer,
152                        ipc_buffer_frame.bits(),
153                    )
154                }))
155            }
156        }
157    }
158
159    /// Corresponds to `seL4_TCB_SetSpace`.
160    pub fn tcb_set_space(
161        self,
162        fault_ep: CPtr,
163        cspace_root: CNode,
164        cspace_root_data: CNodeCapData,
165        vspace_root: VSpace,
166    ) -> Result<()> {
167        Error::wrap(self.invoke(|cptr, ipc_buffer| {
168            ipc_buffer.inner_mut().seL4_TCB_SetSpace(
169                cptr.bits(),
170                fault_ep.bits(),
171                cspace_root.bits(),
172                cspace_root_data.into_word(),
173                vspace_root.bits(),
174                0, /* HACK */
175            )
176        }))
177    }
178
179    sel4_cfg_if! {
180        if #[sel4_cfg(KERNEL_MCS)] {
181            /// Corresponds to `seL4_TCB_SetSchedParams`.
182            pub fn tcb_set_sched_params(
183                self,
184                authority: Tcb,
185                mcp: Word,
186                priority: Word,
187                sched_context: SchedContext,
188                fault_ep: Endpoint,
189            ) -> Result<()> {
190                Error::wrap(self.invoke(|cptr, ipc_buffer| {
191                    ipc_buffer.inner_mut().seL4_TCB_SetSchedParams(
192                        cptr.bits(),
193                        authority.bits(),
194                        mcp,
195                        priority,
196                        sched_context.bits(),
197                        fault_ep.bits(),
198                    )
199                }))
200            }
201        } else {
202            /// Corresponds to `seL4_TCB_SetSchedParams`.
203            pub fn tcb_set_sched_params(self, authority: Tcb, mcp: Word, priority: Word) -> Result<()> {
204                Error::wrap(self.invoke(|cptr, ipc_buffer| {
205                    ipc_buffer.inner_mut().seL4_TCB_SetSchedParams(
206                        cptr.bits(),
207                        authority.bits(),
208                        mcp,
209                        priority,
210                    )
211                }))
212            }
213        }
214    }
215
216    #[sel4_cfg(KERNEL_MCS)]
217    pub fn tcb_set_timeout_endpoint(self, timeout_endpoint: Endpoint) -> Result<()> {
218        Error::wrap(self.invoke(|cptr, ipc_buffer| {
219            ipc_buffer
220                .inner_mut()
221                .seL4_TCB_SetTimeoutEndpoint(cptr.bits(), timeout_endpoint.bits())
222        }))
223    }
224
225    /// Corresponds to `seL4_TCB_SetAffinity`.
226    #[sel4_cfg(all(not(KERNEL_MCS), not(MAX_NUM_NODES = "1")))]
227    pub fn tcb_set_affinity(self, affinity: Word) -> Result<()> {
228        Error::wrap(self.invoke(|cptr, ipc_buffer| {
229            ipc_buffer
230                .inner_mut()
231                .seL4_TCB_SetAffinity(cptr.bits(), affinity)
232        }))
233    }
234
235    /// Corresponds to `seL4_TCB_SetTLSBase`.
236    pub fn tcb_set_tls_base(self, tls_base: Word) -> Result<()> {
237        Error::wrap(self.invoke(|cptr, ipc_buffer| {
238            ipc_buffer
239                .inner_mut()
240                .seL4_TCB_SetTLSBase(cptr.bits(), tls_base)
241        }))
242    }
243
244    /// Corresponds to `seL4_TCB_BindNotification`.
245    pub fn tcb_bind_notification(self, notification: Notification) -> Result<()> {
246        Error::wrap(self.invoke(|cptr, ipc_buffer| {
247            ipc_buffer
248                .inner_mut()
249                .seL4_TCB_BindNotification(cptr.bits(), notification.bits())
250        }))
251    }
252
253    /// Corresponds to `seL4_TCB_UnbindNotification`.
254    pub fn tcb_unbind_notification(self) -> Result<()> {
255        Error::wrap(self.invoke(|cptr, ipc_buffer| {
256            ipc_buffer
257                .inner_mut()
258                .seL4_TCB_UnbindNotification(cptr.bits())
259        }))
260    }
261}
262
263#[sel4_cfg(KERNEL_MCS)]
264impl<C: InvocationContext> SchedControl<C> {
265    /// Corresponds to `seL4_SchedControl_ConfigureFlags`.
266    pub fn sched_control_configure_flags(
267        self,
268        sched_context: SchedContext,
269        budget: Time,
270        period: Time,
271        extra_refills: Word,
272        badge: Badge,
273        flags: Word,
274    ) -> Result<()> {
275        Error::wrap(self.invoke(|cptr, ipc_buffer| {
276            ipc_buffer.inner_mut().seL4_SchedControl_ConfigureFlags(
277                cptr.bits(),
278                sched_context.bits(),
279                budget,
280                period,
281                extra_refills,
282                badge,
283                flags,
284            )
285        }))
286    }
287}
288
289impl<C: InvocationContext> IrqControl<C> {
290    /// Corresponds to `seL4_IRQControl_Get`.
291    pub fn irq_control_get(self, irq: Word, dst: &AbsoluteCPtr) -> Result<()> {
292        Error::wrap(self.invoke(|cptr, ipc_buffer| {
293            ipc_buffer.inner_mut().seL4_IRQControl_Get(
294                cptr.bits(),
295                irq,
296                dst.root().bits(),
297                dst.path().bits(),
298                dst.path().depth_for_kernel(),
299            )
300        }))
301    }
302}
303
304impl<C: InvocationContext> IrqHandler<C> {
305    /// Corresponds to `seL4_IRQHandler_Ack`.
306    pub fn irq_handler_ack(self) -> Result<()> {
307        Error::wrap(
308            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_IRQHandler_Ack(cptr.bits())),
309        )
310    }
311
312    /// Corresponds to `seL4_IRQHandler_SetNotification`.
313    pub fn irq_handler_set_notification(self, notification: Notification) -> Result<()> {
314        Error::wrap(self.invoke(|cptr, ipc_buffer| {
315            ipc_buffer
316                .inner_mut()
317                .seL4_IRQHandler_SetNotification(cptr.bits(), notification.bits())
318        }))
319    }
320
321    /// Corresponds to `seL4_IRQHandler_Clear`.
322    pub fn irq_handler_clear(self) -> Result<()> {
323        Error::wrap(
324            self.invoke(|cptr, ipc_buffer| {
325                ipc_buffer.inner_mut().seL4_IRQHandler_Clear(cptr.bits())
326            }),
327        )
328    }
329}
330
331impl<C: InvocationContext> AbsoluteCPtr<C> {
332    /// Corresponds to `seL4_CNode_Revoke`.
333    pub fn revoke(self) -> Result<()> {
334        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
335            ipc_buffer.inner_mut().seL4_CNode_Revoke(
336                cptr.bits(),
337                path.bits(),
338                path.depth_for_kernel(),
339            )
340        }))
341    }
342
343    /// Corresponds to `seL4_CNode_Delete`.
344    pub fn delete(self) -> Result<()> {
345        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
346            ipc_buffer.inner_mut().seL4_CNode_Delete(
347                cptr.bits(),
348                path.bits(),
349                path.depth_for_kernel(),
350            )
351        }))
352    }
353
354    /// Corresponds to `seL4_CNode_Copy`.
355    pub fn copy(self, src: &AbsoluteCPtr, rights: CapRights) -> Result<()> {
356        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
357            ipc_buffer.inner_mut().seL4_CNode_Copy(
358                cptr.bits(),
359                path.bits(),
360                path.depth_for_kernel(),
361                src.root().bits(),
362                src.path().bits(),
363                src.path().depth_for_kernel(),
364                rights.into_inner(),
365            )
366        }))
367    }
368
369    /// Corresponds to `seL4_CNode_Mint`.
370    pub fn mint(self, src: &AbsoluteCPtr, rights: CapRights, badge: Word) -> Result<()> {
371        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
372            ipc_buffer.inner_mut().seL4_CNode_Mint(
373                cptr.bits(),
374                path.bits(),
375                path.depth_for_kernel(),
376                src.root().bits(),
377                src.path().bits(),
378                src.path().depth_for_kernel(),
379                rights.into_inner(),
380                badge,
381            )
382        }))
383    }
384
385    /// Corresponds to `seL4_CNode_Move`.
386    pub fn move_(self, src: &AbsoluteCPtr) -> Result<()> {
387        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
388            ipc_buffer.inner_mut().seL4_CNode_Move(
389                cptr.bits(),
390                path.bits(),
391                path.depth_for_kernel(),
392                src.root().bits(),
393                src.path().bits(),
394                src.path().depth_for_kernel(),
395            )
396        }))
397    }
398
399    /// Corresponds to `seL4_CNode_Mutate`.
400    pub fn mutate(self, src: &AbsoluteCPtr, badge: Word) -> Result<()> {
401        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
402            ipc_buffer.inner_mut().seL4_CNode_Mutate(
403                cptr.bits(),
404                path.bits(),
405                path.depth_for_kernel(),
406                src.root().bits(),
407                src.path().bits(),
408                src.path().depth_for_kernel(),
409                badge,
410            )
411        }))
412    }
413
414    /// Corresponds to `seL4_CNode_SaveCaller`.
415    #[sel4_cfg(not(KERNEL_MCS))]
416    pub fn save_caller(self) -> Result<()> {
417        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
418            ipc_buffer.inner_mut().seL4_CNode_SaveCaller(
419                cptr.bits(),
420                path.bits(),
421                path.depth_for_kernel(),
422            )
423        }))
424    }
425}