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    AbsoluteCPtr, CNodeCapData, CPtr, CapRights, Error, InvocationContext, ObjectBlueprint, Result,
15    UserContext, Word, cap::*, sys,
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    /// Corresponds to `seL4_TCB_SetPriority`.
110    pub fn tcb_set_priority(self, authority: Tcb, priority: Word) -> Result<()> {
111        Error::wrap(self.invoke(|cptr, ipc_buffer| {
112            ipc_buffer
113                .inner_mut()
114                .seL4_TCB_SetPriority(cptr.bits(), authority.bits(), priority)
115        }))
116    }
117
118    /// Corresponds to `seL4_TCB_SetMCPriority`.
119    pub fn tcb_set_mc_priority(self, authority: Tcb, mcp: Word) -> Result<()> {
120        Error::wrap(self.invoke(|cptr, ipc_buffer| {
121            ipc_buffer
122                .inner_mut()
123                .seL4_TCB_SetMCPriority(cptr.bits(), authority.bits(), mcp)
124        }))
125    }
126
127    sel4_cfg_if! {
128        if #[sel4_cfg(KERNEL_MCS)] {
129            /// Corresponds to `seL4_TCB_Configure`.
130            pub fn tcb_configure(
131                self,
132                cspace_root: CNode,
133                cspace_root_data: CNodeCapData,
134                vspace_root: VSpace,
135                ipc_buffer: Word,
136                ipc_buffer_frame: Granule,
137            ) -> Result<()> {
138                Error::wrap(self.invoke(|cptr, ctx_ipc_buffer| {
139                    ctx_ipc_buffer.inner_mut().seL4_TCB_Configure(
140                        cptr.bits(),
141                        cspace_root.bits(),
142                        cspace_root_data.into_word(),
143                        vspace_root.bits(),
144                        0, /* HACK */
145                        ipc_buffer,
146                        ipc_buffer_frame.bits(),
147                    )
148                }))
149            }
150        } else {
151            /// Corresponds to `seL4_TCB_Configure`.
152            pub fn tcb_configure(
153                self,
154                fault_ep: CPtr,
155                cspace_root: CNode,
156                cspace_root_data: CNodeCapData,
157                vspace_root: VSpace,
158                ipc_buffer: Word,
159                ipc_buffer_frame: Granule,
160            ) -> Result<()> {
161                Error::wrap(self.invoke(|cptr, ctx_ipc_buffer| {
162                    ctx_ipc_buffer.inner_mut().seL4_TCB_Configure(
163                        cptr.bits(),
164                        fault_ep.bits(),
165                        cspace_root.bits(),
166                        cspace_root_data.into_word(),
167                        vspace_root.bits(),
168                        0, /* HACK */
169                        ipc_buffer,
170                        ipc_buffer_frame.bits(),
171                    )
172                }))
173            }
174        }
175    }
176
177    /// Corresponds to `seL4_TCB_SetSpace`.
178    pub fn tcb_set_space(
179        self,
180        fault_ep: CPtr,
181        cspace_root: CNode,
182        cspace_root_data: CNodeCapData,
183        vspace_root: VSpace,
184    ) -> Result<()> {
185        Error::wrap(self.invoke(|cptr, ipc_buffer| {
186            ipc_buffer.inner_mut().seL4_TCB_SetSpace(
187                cptr.bits(),
188                fault_ep.bits(),
189                cspace_root.bits(),
190                cspace_root_data.into_word(),
191                vspace_root.bits(),
192                0, /* HACK */
193            )
194        }))
195    }
196
197    sel4_cfg_if! {
198        if #[sel4_cfg(KERNEL_MCS)] {
199            /// Corresponds to `seL4_TCB_SetSchedParams`.
200            pub fn tcb_set_sched_params(
201                self,
202                authority: Tcb,
203                mcp: Word,
204                priority: Word,
205                sched_context: SchedContext,
206                fault_ep: Endpoint,
207            ) -> Result<()> {
208                Error::wrap(self.invoke(|cptr, ipc_buffer| {
209                    ipc_buffer.inner_mut().seL4_TCB_SetSchedParams(
210                        cptr.bits(),
211                        authority.bits(),
212                        mcp,
213                        priority,
214                        sched_context.bits(),
215                        fault_ep.bits(),
216                    )
217                }))
218            }
219        } else {
220            /// Corresponds to `seL4_TCB_SetSchedParams`.
221            pub fn tcb_set_sched_params(self, authority: Tcb, mcp: Word, priority: Word) -> Result<()> {
222                Error::wrap(self.invoke(|cptr, ipc_buffer| {
223                    ipc_buffer.inner_mut().seL4_TCB_SetSchedParams(
224                        cptr.bits(),
225                        authority.bits(),
226                        mcp,
227                        priority,
228                    )
229                }))
230            }
231        }
232    }
233
234    #[sel4_cfg(KERNEL_MCS)]
235    pub fn tcb_set_timeout_endpoint(self, timeout_endpoint: Endpoint) -> Result<()> {
236        Error::wrap(self.invoke(|cptr, ipc_buffer| {
237            ipc_buffer
238                .inner_mut()
239                .seL4_TCB_SetTimeoutEndpoint(cptr.bits(), timeout_endpoint.bits())
240        }))
241    }
242
243    /// Corresponds to `seL4_TCB_SetAffinity`.
244    #[sel4_cfg(all(not(KERNEL_MCS), not(MAX_NUM_NODES = "1")))]
245    pub fn tcb_set_affinity(self, affinity: Word) -> Result<()> {
246        Error::wrap(self.invoke(|cptr, ipc_buffer| {
247            ipc_buffer
248                .inner_mut()
249                .seL4_TCB_SetAffinity(cptr.bits(), affinity)
250        }))
251    }
252
253    /// Corresponds to `seL4_TCB_SetTLSBase`.
254    pub fn tcb_set_tls_base(self, tls_base: Word) -> Result<()> {
255        Error::wrap(self.invoke(|cptr, ipc_buffer| {
256            ipc_buffer
257                .inner_mut()
258                .seL4_TCB_SetTLSBase(cptr.bits(), tls_base)
259        }))
260    }
261
262    /// Corresponds to `seL4_TCB_BindNotification`.
263    pub fn tcb_bind_notification(self, notification: Notification) -> Result<()> {
264        Error::wrap(self.invoke(|cptr, ipc_buffer| {
265            ipc_buffer
266                .inner_mut()
267                .seL4_TCB_BindNotification(cptr.bits(), notification.bits())
268        }))
269    }
270
271    /// Corresponds to `seL4_TCB_UnbindNotification`.
272    pub fn tcb_unbind_notification(self) -> Result<()> {
273        Error::wrap(self.invoke(|cptr, ipc_buffer| {
274            ipc_buffer
275                .inner_mut()
276                .seL4_TCB_UnbindNotification(cptr.bits())
277        }))
278    }
279}
280
281#[sel4_cfg(KERNEL_MCS)]
282impl<C: InvocationContext> SchedControl<C> {
283    /// Corresponds to `seL4_SchedControl_ConfigureFlags`.
284    pub fn sched_control_configure_flags(
285        self,
286        sched_context: SchedContext,
287        budget: Time,
288        period: Time,
289        extra_refills: Word,
290        badge: Badge,
291        flags: Word,
292    ) -> Result<()> {
293        Error::wrap(self.invoke(|cptr, ipc_buffer| {
294            ipc_buffer.inner_mut().seL4_SchedControl_ConfigureFlags(
295                cptr.bits(),
296                sched_context.bits(),
297                budget,
298                period,
299                extra_refills,
300                badge,
301                flags,
302            )
303        }))
304    }
305}
306
307#[sel4_cfg(KERNEL_MCS)]
308impl<C: InvocationContext> SchedContext<C> {
309    /// Corresponds to `seL4_SchedContext_Unbind`.
310    pub fn unbind(self) -> Result<()> {
311        Error::wrap(self.invoke(|cptr, ipc_buffer| {
312            ipc_buffer.inner_mut().seL4_SchedContext_Unbind(cptr.bits())
313        }))
314    }
315}
316
317impl<C: InvocationContext> IrqControl<C> {
318    /// Corresponds to `seL4_IRQControl_Get`.
319    pub fn irq_control_get(self, irq: Word, dst: &AbsoluteCPtr) -> Result<()> {
320        Error::wrap(self.invoke(|cptr, ipc_buffer| {
321            ipc_buffer.inner_mut().seL4_IRQControl_Get(
322                cptr.bits(),
323                irq,
324                dst.root().bits(),
325                dst.path().bits(),
326                dst.path().depth_for_kernel(),
327            )
328        }))
329    }
330}
331
332impl<C: InvocationContext> IrqHandler<C> {
333    /// Corresponds to `seL4_IRQHandler_Ack`.
334    pub fn irq_handler_ack(self) -> Result<()> {
335        Error::wrap(
336            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_IRQHandler_Ack(cptr.bits())),
337        )
338    }
339
340    /// Corresponds to `seL4_IRQHandler_SetNotification`.
341    pub fn irq_handler_set_notification(self, notification: Notification) -> Result<()> {
342        Error::wrap(self.invoke(|cptr, ipc_buffer| {
343            ipc_buffer
344                .inner_mut()
345                .seL4_IRQHandler_SetNotification(cptr.bits(), notification.bits())
346        }))
347    }
348
349    /// Corresponds to `seL4_IRQHandler_Clear`.
350    pub fn irq_handler_clear(self) -> Result<()> {
351        Error::wrap(
352            self.invoke(|cptr, ipc_buffer| {
353                ipc_buffer.inner_mut().seL4_IRQHandler_Clear(cptr.bits())
354            }),
355        )
356    }
357}
358
359impl<C: InvocationContext> AbsoluteCPtr<C> {
360    /// Corresponds to `seL4_CNode_Revoke`.
361    pub fn revoke(self) -> Result<()> {
362        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
363            ipc_buffer.inner_mut().seL4_CNode_Revoke(
364                cptr.bits(),
365                path.bits(),
366                path.depth_for_kernel(),
367            )
368        }))
369    }
370
371    /// Corresponds to `seL4_CNode_Delete`.
372    pub fn delete(self) -> Result<()> {
373        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
374            ipc_buffer.inner_mut().seL4_CNode_Delete(
375                cptr.bits(),
376                path.bits(),
377                path.depth_for_kernel(),
378            )
379        }))
380    }
381
382    /// Corresponds to `seL4_CNode_Copy`.
383    pub fn copy(self, src: &AbsoluteCPtr, rights: CapRights) -> Result<()> {
384        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
385            ipc_buffer.inner_mut().seL4_CNode_Copy(
386                cptr.bits(),
387                path.bits(),
388                path.depth_for_kernel(),
389                src.root().bits(),
390                src.path().bits(),
391                src.path().depth_for_kernel(),
392                rights.into_inner(),
393            )
394        }))
395    }
396
397    /// Corresponds to `seL4_CNode_Mint`.
398    pub fn mint(self, src: &AbsoluteCPtr, rights: CapRights, badge: Word) -> Result<()> {
399        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
400            ipc_buffer.inner_mut().seL4_CNode_Mint(
401                cptr.bits(),
402                path.bits(),
403                path.depth_for_kernel(),
404                src.root().bits(),
405                src.path().bits(),
406                src.path().depth_for_kernel(),
407                rights.into_inner(),
408                badge,
409            )
410        }))
411    }
412
413    /// Corresponds to `seL4_CNode_Move`.
414    pub fn move_(self, src: &AbsoluteCPtr) -> Result<()> {
415        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
416            ipc_buffer.inner_mut().seL4_CNode_Move(
417                cptr.bits(),
418                path.bits(),
419                path.depth_for_kernel(),
420                src.root().bits(),
421                src.path().bits(),
422                src.path().depth_for_kernel(),
423            )
424        }))
425    }
426
427    /// Corresponds to `seL4_CNode_Mutate`.
428    pub fn mutate(self, src: &AbsoluteCPtr, badge: Word) -> Result<()> {
429        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
430            ipc_buffer.inner_mut().seL4_CNode_Mutate(
431                cptr.bits(),
432                path.bits(),
433                path.depth_for_kernel(),
434                src.root().bits(),
435                src.path().bits(),
436                src.path().depth_for_kernel(),
437                badge,
438            )
439        }))
440    }
441
442    /// Corresponds to `seL4_CNode_SaveCaller`.
443    #[sel4_cfg(not(KERNEL_MCS))]
444    pub fn save_caller(self) -> Result<()> {
445        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
446            ipc_buffer.inner_mut().seL4_CNode_SaveCaller(
447                cptr.bits(),
448                path.bits(),
449                path.depth_for_kernel(),
450            )
451        }))
452    }
453}