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