1#![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
21pub type Time = u64;
23
24impl<C: InvocationContext> Untyped<C> {
25 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 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 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 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 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 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 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 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 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, ipc_buffer,
187 ipc_buffer_frame.bits(),
188 )
189 }))
190 }
191 } else {
192 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, ipc_buffer,
211 ipc_buffer_frame.bits(),
212 )
213 }))
214 }
215 }
216 }
217
218 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, )
235 }))
236 }
237
238 sel4_cfg_if! {
239 if #[sel4_cfg(KERNEL_MCS)] {
240 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 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 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 #[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}