sel4_microkit_base/
ipc.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7use core::fmt;
8
9use crate::{Channel, Child, MessageInfo, defer::PreparedDeferredAction};
10
11const INPUT_CAP: sel4::cap::Endpoint = sel4::Cap::from_bits(1);
12const REPLY_CAP: sel4::cap::Reply = sel4::Cap::from_bits(4);
13const MONITOR_EP_CAP: sel4::cap::Endpoint = sel4::Cap::from_bits(5);
14
15const IS_ENDPOINT_BADGE_BIT: usize = 63;
16const IS_FAULT_BADGE_BIT: usize = 62;
17
18fn strip_flag(badge: sel4::Badge, bit: usize) -> Option<sel4::Word> {
19    let mask = 1 << bit;
20    if badge & mask != 0 {
21        Some(badge & !mask)
22    } else {
23        None
24    }
25}
26
27#[doc(hidden)]
28#[derive(Debug, Clone)]
29pub enum Event {
30    Notified(ChannelSet),
31    Protected(Channel, MessageInfo),
32    Fault(Child, MessageInfo),
33}
34
35impl Event {
36    fn new(tag: sel4::MessageInfo, badge: sel4::Badge) -> Self {
37        if let Some(channel_index) = strip_flag(badge, IS_ENDPOINT_BADGE_BIT) {
38            Self::Protected(
39                Channel::new(channel_index.try_into().unwrap()),
40                MessageInfo::from_inner(tag),
41            )
42        } else if let Some(pd_index) = strip_flag(badge, IS_FAULT_BADGE_BIT) {
43            Self::Fault(
44                Child::new(pd_index.try_into().unwrap()),
45                MessageInfo::from_inner(tag),
46            )
47        } else {
48            Self::Notified(ChannelSet(badge))
49        }
50    }
51
52    fn from_recv(recv: (sel4::MessageInfo, sel4::Badge)) -> Self {
53        Self::new(recv.0, recv.1)
54    }
55}
56
57#[doc(hidden)]
58#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
59pub struct ChannelSet(sel4::Badge);
60
61impl ChannelSet {
62    pub fn contains(&self, channel: Channel) -> bool {
63        (self.0 & (1 << channel.index())) != 0
64    }
65
66    pub fn iter(&self) -> ChannelSetIter {
67        ChannelSetIter(self.0)
68    }
69
70    pub fn display(&self) -> DisplayChannelSet<'_> {
71        DisplayChannelSet(self)
72    }
73}
74
75#[doc(hidden)]
76pub struct ChannelSetIter(sel4::Badge);
77
78impl Iterator for ChannelSetIter {
79    type Item = Channel;
80
81    fn next(&mut self) -> Option<Self::Item> {
82        let badge_bits = self.0;
83        match badge_bits {
84            0 => None,
85            _ => {
86                let i = badge_bits.trailing_zeros();
87                self.0 = badge_bits & !(1 << i);
88                Some(Channel::new(i.try_into().unwrap()))
89            }
90        }
91    }
92}
93
94pub struct DisplayChannelSet<'a>(&'a ChannelSet);
95
96impl fmt::Display for DisplayChannelSet<'_> {
97    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98        write!(f, "{{")?;
99        let mut first = true;
100        for channel in self.0.iter() {
101            if !first {
102                write!(f, ", ")?;
103            }
104            write!(f, "{}", channel.index())?;
105            first = false;
106        }
107        write!(f, "}}")?;
108        Ok(())
109    }
110}
111
112pub fn reply(msg_info: MessageInfo) {
113    REPLY_CAP.send(msg_info.into_inner())
114}
115
116pub fn recv() -> Event {
117    Event::from_recv(INPUT_CAP.recv(REPLY_CAP))
118}
119
120pub fn reply_recv(msg_info: MessageInfo) -> Event {
121    Event::from_recv(INPUT_CAP.reply_recv(msg_info.into_inner(), REPLY_CAP))
122}
123
124pub(crate) fn nb_send_recv(action: PreparedDeferredAction) -> Event {
125    Event::from_recv(action.cptr().nb_send_recv(
126        action.msg_info(),
127        INPUT_CAP.cast::<sel4::cap_type::Unspecified>(),
128        REPLY_CAP,
129    ))
130}
131
132pub(crate) fn forfeit_sc() -> PreparedDeferredAction {
133    PreparedDeferredAction::new(
134        MONITOR_EP_CAP.cast(),
135        sel4::MessageInfoBuilder::default().build(),
136    )
137}