sel4_microkit_base/
handler.rs1use core::fmt;
8
9#[cfg(feature = "alloc")]
10use alloc::boxed::Box;
11
12use crate::{
13 Channel, Child, MessageInfo,
14 defer::{DeferredAction, PreparedDeferredAction},
15 ipc::{self, ChannelSet, Event},
16 pd_is_passive, symbols,
17};
18
19pub use core::convert::Infallible;
20
21pub trait Handler {
23 type Error: fmt::Display;
25
26 fn notified(&mut self, channels: ChannelSet) -> Result<(), Self::Error> {
30 panic!(
31 "unexpected notification from channels {}",
32 channels.display()
33 )
34 }
35
36 fn protected(
40 &mut self,
41 channel: Channel,
42 msg_info: MessageInfo,
43 ) -> Result<MessageInfo, Self::Error> {
44 panic!(
45 "unexpected protected procedure call from channel {channel:?} with msg_info={msg_info:?}"
46 )
47 }
48
49 fn fault(
53 &mut self,
54 child: Child,
55 msg_info: MessageInfo,
56 ) -> Result<Option<MessageInfo>, Self::Error> {
57 panic!("unexpected fault from protection domain {child:?} with msg_info={msg_info:?}")
58 }
59
60 fn take_deferred_action(&mut self) -> Option<DeferredAction> {
66 None
67 }
68
69 #[doc(hidden)]
70 fn run(&mut self) -> Result<Never, Self::Error> {
71 let mut reply_tag: Option<MessageInfo> = None;
72
73 let mut prepared_deferred_action: Option<PreparedDeferredAction> = if pd_is_passive() {
74 Some(ipc::forfeit_sc())
75 } else {
76 None
77 };
78
79 {
81 let mut bits = symbols::pd_irqs();
82 while bits != 0 {
83 let i = bits.trailing_zeros();
84 Channel::new(i.try_into().unwrap()).irq_ack().unwrap();
85 bits &= bits - 1; }
87 }
88
89 loop {
90 let event = match (reply_tag.take(), prepared_deferred_action.take()) {
91 (Some(msg_info), action_opt) => {
92 if let Some(action) = action_opt {
93 ipc::send(action);
94 }
95 ipc::reply_recv(msg_info)
96 }
97 (None, Some(action)) => ipc::nb_send_recv(action),
98 (None, None) => ipc::recv(),
99 };
100
101 match event {
102 Event::Notified(channels) => {
103 self.notified(channels)?;
104 }
105 Event::Protected(channel, msg_info) => {
106 reply_tag = Some(self.protected(channel, msg_info)?);
107 }
108 Event::Fault(child, msg_info) => {
109 reply_tag = self.fault(child, msg_info)?;
110 }
111 };
112
113 prepared_deferred_action = self
114 .take_deferred_action()
115 .as_ref()
116 .map(DeferredAction::prepare);
117 }
118 }
119}
120
121#[doc(hidden)]
122pub enum Never {}
123
124impl Handler for Never {
125 type Error = Infallible;
126}
127
128pub struct NullHandler(());
130
131impl NullHandler {
132 #[allow(clippy::new_without_default)]
133 pub fn new() -> Self {
134 Self(())
135 }
136}
137
138impl Handler for NullHandler {
139 type Error = Infallible;
140}
141
142#[cfg(feature = "alloc")]
143impl<T: Handler + ?Sized> Handler for Box<T> {
144 type Error = T::Error;
145
146 fn notified(&mut self, channels: ChannelSet) -> Result<(), Self::Error> {
147 (**self).notified(channels)
148 }
149
150 fn protected(
151 &mut self,
152 channel: Channel,
153 msg_info: MessageInfo,
154 ) -> Result<MessageInfo, Self::Error> {
155 (**self).protected(channel, msg_info)
156 }
157
158 fn fault(
159 &mut self,
160 child: Child,
161 msg_info: MessageInfo,
162 ) -> Result<Option<MessageInfo>, Self::Error> {
163 (**self).fault(child, msg_info)
164 }
165
166 fn take_deferred_action(&mut self) -> Option<DeferredAction> {
167 (**self).take_deferred_action()
168 }
169
170 #[doc(hidden)]
171 fn run(&mut self) -> Result<Never, Self::Error> {
172 (**self).run()
173 }
174}