Skip to main content

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`.
22pub type Time = u64;
23
24impl<C: InvocationContext> Untyped<C> {
25    /// Corresponds to `seL4_Untyped_Retype`.
26    pub fn untyped_retype(
27        self,
28        blueprint: &ObjectBlueprint,
29        dst: &AbsoluteCPtr,
30        dst_offset: usize,
31        num_objects: usize,
32    ) -> Result<()> {
33        Error::wrap(self.invoke(|cptr, ipc_buffer| {
34            ipc_buffer.inner_mut().seL4_Untyped_Retype(
35                cptr.bits(),
36                blueprint.ty().into_sys().into(),
37                blueprint.api_size_bits().unwrap_or(0).try_into().unwrap(),
38                dst.root().bits(),
39                dst.path().bits(),
40                dst.path().depth().try_into().unwrap(),
41                dst_offset.try_into().unwrap(),
42                num_objects.try_into().unwrap(),
43            )
44        }))
45    }
46}
47
48const USER_CONTEXT_MAX_REG_COUNT: usize =
49    mem::size_of::<sys::seL4_UserContext>() / mem::size_of::<Word>();
50
51#[derive(Debug, Clone, PartialEq)]
52pub struct TcbFlagsBuilder(Word);
53
54impl TcbFlagsBuilder {
55    pub fn new() -> Self {
56        Self(sel4_sys::seL4_TCBFlag::seL4_TCBFlag_NoFlag)
57    }
58
59    pub fn build(self) -> Word {
60        self.0
61    }
62
63    pub fn fpu_disabled(self, val: bool) -> Self {
64        self.apply_flag_val(sel4_sys::seL4_TCBFlag::seL4_TCBFlag_fpuDisabled, val)
65    }
66
67    fn apply_flag_val(mut self, flag: Word, val: bool) -> Self {
68        if val {
69            self.0 |= flag
70        } else {
71            self.0 &= !flag
72        }
73        self
74    }
75}
76
77impl Default for TcbFlagsBuilder {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83impl<C: InvocationContext> Tcb<C> {
84    /// Corresponds to `seL4_TCB_ReadRegisters`.
85    pub fn tcb_read_registers(self, suspend: bool, count: Word) -> Result<UserContext> {
86        let mut regs: UserContext = Default::default();
87        let err = self.invoke(|cptr, ipc_buffer| {
88            ipc_buffer.inner_mut().seL4_TCB_ReadRegisters(
89                cptr.bits(),
90                suspend.into(),
91                0,
92                count,
93                regs.inner_mut(),
94            )
95        });
96        Error::or(err, regs)
97    }
98
99    pub fn tcb_read_all_registers(self, suspend: bool) -> Result<UserContext> {
100        self.tcb_read_registers(suspend, USER_CONTEXT_MAX_REG_COUNT.try_into().unwrap())
101    }
102
103    /// Corresponds to `seL4_TCB_WriteRegisters`.
104    // HACK should not be mut
105    pub fn tcb_write_registers(
106        self,
107        resume: bool,
108        count: Word,
109        regs: &mut UserContext,
110    ) -> Result<()> {
111        Error::wrap(self.invoke(|cptr, ipc_buffer| {
112            ipc_buffer.inner_mut().seL4_TCB_WriteRegisters(
113                cptr.bits(),
114                resume.into(),
115                0,
116                count,
117                regs.inner_mut(),
118            )
119        }))
120    }
121
122    pub fn tcb_write_all_registers(self, resume: bool, regs: &mut UserContext) -> Result<()> {
123        self.tcb_write_registers(resume, USER_CONTEXT_MAX_REG_COUNT.try_into().unwrap(), regs)
124    }
125
126    /// Corresponds to `seL4_TCB_Resume`.
127    pub fn tcb_resume(self) -> Result<()> {
128        Error::wrap(
129            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_TCB_Resume(cptr.bits())),
130        )
131    }
132
133    /// Corresponds to `seL4_TCB_Suspend`.
134    pub fn tcb_suspend(self) -> Result<()> {
135        Error::wrap(
136            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_TCB_Suspend(cptr.bits())),
137        )
138    }
139
140    /// Corresponds to `seL4_TCB_SetPriority`.
141    pub fn tcb_set_priority(self, authority: Tcb, priority: Word) -> Result<()> {
142        Error::wrap(self.invoke(|cptr, ipc_buffer| {
143            ipc_buffer
144                .inner_mut()
145                .seL4_TCB_SetPriority(cptr.bits(), authority.bits(), priority)
146        }))
147    }
148
149    /// Corresponds to `seL4_TCB_SetMCPriority`.
150    pub fn tcb_set_mc_priority(self, authority: Tcb, mcp: Word) -> Result<()> {
151        Error::wrap(self.invoke(|cptr, ipc_buffer| {
152            ipc_buffer
153                .inner_mut()
154                .seL4_TCB_SetMCPriority(cptr.bits(), authority.bits(), mcp)
155        }))
156    }
157
158    // Corresponds to `seL4_TCB_SetFlags`.
159    pub fn tcb_set_flags(self, clear: Word, set: Word) -> Result<Word> {
160        let ret = self.invoke(|cptr, ipc_buffer| {
161            ipc_buffer
162                .inner_mut()
163                .seL4_TCB_SetFlags(cptr.bits(), clear, set)
164        });
165        Error::or(ret.error, ret.flags)
166    }
167
168    sel4_cfg_if! {
169        if #[sel4_cfg(KERNEL_MCS)] {
170            /// Corresponds to `seL4_TCB_Configure`.
171            pub fn tcb_configure(
172                self,
173                cspace_root: CNode,
174                cspace_root_data: CNodeCapData,
175                vspace_root: VSpace,
176                ipc_buffer: Word,
177                ipc_buffer_frame: Granule,
178            ) -> Result<()> {
179                Error::wrap(self.invoke(|cptr, ctx_ipc_buffer| {
180                    ctx_ipc_buffer.inner_mut().seL4_TCB_Configure(
181                        cptr.bits(),
182                        cspace_root.bits(),
183                        cspace_root_data.into_word(),
184                        vspace_root.bits(),
185                        0, /* HACK */
186                        ipc_buffer,
187                        ipc_buffer_frame.bits(),
188                    )
189                }))
190            }
191        } else {
192            /// Corresponds to `seL4_TCB_Configure`.
193            pub fn tcb_configure(
194                self,
195                fault_ep: CPtr,
196                cspace_root: CNode,
197                cspace_root_data: CNodeCapData,
198                vspace_root: VSpace,
199                ipc_buffer: Word,
200                ipc_buffer_frame: Granule,
201            ) -> Result<()> {
202                Error::wrap(self.invoke(|cptr, ctx_ipc_buffer| {
203                    ctx_ipc_buffer.inner_mut().seL4_TCB_Configure(
204                        cptr.bits(),
205                        fault_ep.bits(),
206                        cspace_root.bits(),
207                        cspace_root_data.into_word(),
208                        vspace_root.bits(),
209                        0, /* HACK */
210                        ipc_buffer,
211                        ipc_buffer_frame.bits(),
212                    )
213                }))
214            }
215        }
216    }
217
218    /// Corresponds to `seL4_TCB_SetSpace`.
219    pub fn tcb_set_space(
220        self,
221        fault_ep: CPtr,
222        cspace_root: CNode,
223        cspace_root_data: CNodeCapData,
224        vspace_root: VSpace,
225    ) -> Result<()> {
226        Error::wrap(self.invoke(|cptr, ipc_buffer| {
227            ipc_buffer.inner_mut().seL4_TCB_SetSpace(
228                cptr.bits(),
229                fault_ep.bits(),
230                cspace_root.bits(),
231                cspace_root_data.into_word(),
232                vspace_root.bits(),
233                0, /* HACK */
234            )
235        }))
236    }
237
238    sel4_cfg_if! {
239        if #[sel4_cfg(KERNEL_MCS)] {
240            /// Corresponds to `seL4_TCB_SetSchedParams`.
241            pub fn tcb_set_sched_params(
242                self,
243                authority: Tcb,
244                mcp: Word,
245                priority: Word,
246                sched_context: SchedContext,
247                fault_ep: Endpoint,
248            ) -> Result<()> {
249                Error::wrap(self.invoke(|cptr, ipc_buffer| {
250                    ipc_buffer.inner_mut().seL4_TCB_SetSchedParams(
251                        cptr.bits(),
252                        authority.bits(),
253                        mcp,
254                        priority,
255                        sched_context.bits(),
256                        fault_ep.bits(),
257                    )
258                }))
259            }
260        } else {
261            /// Corresponds to `seL4_TCB_SetSchedParams`.
262            pub fn tcb_set_sched_params(self, authority: Tcb, mcp: Word, priority: Word) -> Result<()> {
263                Error::wrap(self.invoke(|cptr, ipc_buffer| {
264                    ipc_buffer.inner_mut().seL4_TCB_SetSchedParams(
265                        cptr.bits(),
266                        authority.bits(),
267                        mcp,
268                        priority,
269                    )
270                }))
271            }
272        }
273    }
274
275    #[sel4_cfg(KERNEL_MCS)]
276    pub fn tcb_set_timeout_endpoint(self, timeout_endpoint: Endpoint) -> Result<()> {
277        Error::wrap(self.invoke(|cptr, ipc_buffer| {
278            ipc_buffer
279                .inner_mut()
280                .seL4_TCB_SetTimeoutEndpoint(cptr.bits(), timeout_endpoint.bits())
281        }))
282    }
283
284    /// Corresponds to `seL4_TCB_SetAffinity`.
285    #[sel4_cfg(all(not(KERNEL_MCS), not(MAX_NUM_NODES = "1")))]
286    pub fn tcb_set_affinity(self, affinity: Word) -> Result<()> {
287        Error::wrap(self.invoke(|cptr, ipc_buffer| {
288            ipc_buffer
289                .inner_mut()
290                .seL4_TCB_SetAffinity(cptr.bits(), affinity)
291        }))
292    }
293
294    /// Corresponds to `seL4_TCB_SetTLSBase`.
295    pub fn tcb_set_tls_base(self, tls_base: Word) -> Result<()> {
296        Error::wrap(self.invoke(|cptr, ipc_buffer| {
297            ipc_buffer
298                .inner_mut()
299                .seL4_TCB_SetTLSBase(cptr.bits(), tls_base)
300        }))
301    }
302
303    /// Corresponds to `seL4_TCB_BindNotification`.
304    pub fn tcb_bind_notification(self, notification: Notification) -> Result<()> {
305        Error::wrap(self.invoke(|cptr, ipc_buffer| {
306            ipc_buffer
307                .inner_mut()
308                .seL4_TCB_BindNotification(cptr.bits(), notification.bits())
309        }))
310    }
311
312    /// Corresponds to `seL4_TCB_UnbindNotification`.
313    pub fn tcb_unbind_notification(self) -> Result<()> {
314        Error::wrap(self.invoke(|cptr, ipc_buffer| {
315            ipc_buffer
316                .inner_mut()
317                .seL4_TCB_UnbindNotification(cptr.bits())
318        }))
319    }
320}
321
322#[sel4_cfg(KERNEL_MCS)]
323impl<C: InvocationContext> SchedControl<C> {
324    /// Corresponds to `seL4_SchedControl_ConfigureFlags`.
325    pub fn sched_control_configure_flags(
326        self,
327        sched_context: SchedContext,
328        budget: Time,
329        period: Time,
330        extra_refills: Word,
331        badge: Badge,
332        flags: Word,
333    ) -> Result<()> {
334        Error::wrap(self.invoke(|cptr, ipc_buffer| {
335            ipc_buffer.inner_mut().seL4_SchedControl_ConfigureFlags(
336                cptr.bits(),
337                sched_context.bits(),
338                budget,
339                period,
340                extra_refills,
341                badge,
342                flags,
343            )
344        }))
345    }
346}
347
348#[sel4_cfg(KERNEL_MCS)]
349impl<C: InvocationContext> SchedContext<C> {
350    /// Corresponds to `seL4_SchedContext_Unbind`.
351    pub fn unbind(self) -> Result<()> {
352        Error::wrap(self.invoke(|cptr, ipc_buffer| {
353            ipc_buffer.inner_mut().seL4_SchedContext_Unbind(cptr.bits())
354        }))
355    }
356}
357
358impl<C: InvocationContext> IrqControl<C> {
359    /// Corresponds to `seL4_IRQControl_Get`.
360    pub fn irq_control_get(self, irq: Word, dst: &AbsoluteCPtr) -> Result<()> {
361        Error::wrap(self.invoke(|cptr, ipc_buffer| {
362            ipc_buffer.inner_mut().seL4_IRQControl_Get(
363                cptr.bits(),
364                irq,
365                dst.root().bits(),
366                dst.path().bits(),
367                dst.path().depth_for_kernel(),
368            )
369        }))
370    }
371}
372
373impl<C: InvocationContext> IrqHandler<C> {
374    /// Corresponds to `seL4_IRQHandler_Ack`.
375    pub fn irq_handler_ack(self) -> Result<()> {
376        Error::wrap(
377            self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_IRQHandler_Ack(cptr.bits())),
378        )
379    }
380
381    /// Corresponds to `seL4_IRQHandler_SetNotification`.
382    pub fn irq_handler_set_notification(self, notification: Notification) -> Result<()> {
383        Error::wrap(self.invoke(|cptr, ipc_buffer| {
384            ipc_buffer
385                .inner_mut()
386                .seL4_IRQHandler_SetNotification(cptr.bits(), notification.bits())
387        }))
388    }
389
390    /// Corresponds to `seL4_IRQHandler_Clear`.
391    pub fn irq_handler_clear(self) -> Result<()> {
392        Error::wrap(
393            self.invoke(|cptr, ipc_buffer| {
394                ipc_buffer.inner_mut().seL4_IRQHandler_Clear(cptr.bits())
395            }),
396        )
397    }
398}
399
400impl<C: InvocationContext> DomainSet<C> {
401    /// Corresponds to `seL4_DomainSet_Set`.
402    pub fn domain_set_set(self, domain: u8, thread: Tcb) -> Result<()> {
403        Error::wrap(self.invoke(|cptr, ipc_buffer| {
404            ipc_buffer
405                .inner_mut()
406                .seL4_DomainSet_Set(cptr.bits(), domain, thread.bits())
407        }))
408    }
409
410    /// Corresponds to `seL4_DomainSet_ScheduleConfigure`
411    pub fn domain_set_schedule_configure(
412        self,
413        index: Word,
414        domain: u8,
415        duration: Time,
416    ) -> Result<()> {
417        Error::wrap(self.invoke(|cptr, ipc_buffer| {
418            ipc_buffer.inner_mut().seL4_DomainSet_ScheduleConfigure(
419                cptr.bits(),
420                index,
421                domain,
422                duration,
423            )
424        }))
425    }
426
427    /// Corresponds to `seL4_DomainSet_ScheduleSetStart`
428    pub fn domain_set_schedule_set_start(self, index: Word) -> Result<()> {
429        Error::wrap(self.invoke(|cptr, ipc_buffer| {
430            ipc_buffer
431                .inner_mut()
432                .seL4_DomainSet_ScheduleSetStart(cptr.bits(), index)
433        }))
434    }
435}
436
437impl<C: InvocationContext> AbsoluteCPtr<C> {
438    /// Corresponds to `seL4_CNode_Revoke`.
439    pub fn revoke(self) -> Result<()> {
440        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
441            ipc_buffer.inner_mut().seL4_CNode_Revoke(
442                cptr.bits(),
443                path.bits(),
444                path.depth_for_kernel(),
445            )
446        }))
447    }
448
449    /// Corresponds to `seL4_CNode_Delete`.
450    pub fn delete(self) -> Result<()> {
451        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
452            ipc_buffer.inner_mut().seL4_CNode_Delete(
453                cptr.bits(),
454                path.bits(),
455                path.depth_for_kernel(),
456            )
457        }))
458    }
459
460    /// Corresponds to `seL4_CNode_Copy`.
461    pub fn copy(self, src: &AbsoluteCPtr, rights: CapRights) -> Result<()> {
462        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
463            ipc_buffer.inner_mut().seL4_CNode_Copy(
464                cptr.bits(),
465                path.bits(),
466                path.depth_for_kernel(),
467                src.root().bits(),
468                src.path().bits(),
469                src.path().depth_for_kernel(),
470                rights.into_inner(),
471            )
472        }))
473    }
474
475    /// Corresponds to `seL4_CNode_Mint`.
476    pub fn mint(self, src: &AbsoluteCPtr, rights: CapRights, badge: Word) -> Result<()> {
477        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
478            ipc_buffer.inner_mut().seL4_CNode_Mint(
479                cptr.bits(),
480                path.bits(),
481                path.depth_for_kernel(),
482                src.root().bits(),
483                src.path().bits(),
484                src.path().depth_for_kernel(),
485                rights.into_inner(),
486                badge,
487            )
488        }))
489    }
490
491    /// Corresponds to `seL4_CNode_Move`.
492    pub fn move_(self, src: &AbsoluteCPtr) -> Result<()> {
493        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
494            ipc_buffer.inner_mut().seL4_CNode_Move(
495                cptr.bits(),
496                path.bits(),
497                path.depth_for_kernel(),
498                src.root().bits(),
499                src.path().bits(),
500                src.path().depth_for_kernel(),
501            )
502        }))
503    }
504
505    /// Corresponds to `seL4_CNode_Mutate`.
506    pub fn mutate(self, src: &AbsoluteCPtr, badge: Word) -> Result<()> {
507        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
508            ipc_buffer.inner_mut().seL4_CNode_Mutate(
509                cptr.bits(),
510                path.bits(),
511                path.depth_for_kernel(),
512                src.root().bits(),
513                src.path().bits(),
514                src.path().depth_for_kernel(),
515                badge,
516            )
517        }))
518    }
519
520    /// Corresponds to `seL4_CNode_SaveCaller`.
521    #[sel4_cfg(not(KERNEL_MCS))]
522    pub fn save_caller(self) -> Result<()> {
523        Error::wrap(self.invoke(|cptr, path, ipc_buffer| {
524            ipc_buffer.inner_mut().seL4_CNode_SaveCaller(
525                cptr.bits(),
526                path.bits(),
527                path.depth_for_kernel(),
528            )
529        }))
530    }
531}