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