1use core::array;
8
9use sel4_config::{sel4_cfg, sel4_cfg_if};
10
11use crate::{
12 Cap, CapType, ConveysReplyAuthority, InvocationContext, MessageInfo,
13 NUM_FAST_MESSAGE_REGISTERS, Word, cap, const_helpers::u32_into_usize, sys,
14};
15
16#[sel4_cfg(not(KERNEL_MCS))]
17use crate::IpcBuffer;
18
19pub const NUM_MESSAGE_REGISTERS: usize = u32_into_usize(sys::seL4_MsgLimits::seL4_MsgMaxLength);
21
22pub type Badge = Word;
24
25sel4_cfg_if! {
26 if #[sel4_cfg(KERNEL_MCS)] {
27 pub type WaitMessageInfo = MessageInfo;
28
29 fn wait_message_info_from_sys(info: sys::WaitMessageInfo) -> WaitMessageInfo {
30 MessageInfo::from_inner(info)
31 }
32 } else {
33 pub type WaitMessageInfo = ();
34
35 fn wait_message_info_from_sys(info: sys::WaitMessageInfo) -> WaitMessageInfo {
36 info
37 }
38 }
39}
40
41impl<T: CapType, C: InvocationContext> Cap<T, C> {
42 pub fn send(self, info: MessageInfo) {
44 self.invoke(|cptr, ipc_buffer| {
45 ipc_buffer
46 .inner_mut()
47 .seL4_Send(cptr.bits(), info.into_inner())
48 })
49 }
50
51 pub fn nb_send(self, info: MessageInfo) {
53 self.invoke(|cptr, ipc_buffer| {
54 ipc_buffer
55 .inner_mut()
56 .seL4_NBSend(cptr.bits(), info.into_inner())
57 })
58 }
59
60 #[sel4_cfg(KERNEL_MCS)]
62 pub fn nb_send_recv<U: CapType>(
63 self,
64 info: MessageInfo,
65 src: Cap<U>,
66 reply_authority: impl ConveysReplyAuthority,
67 ) -> (MessageInfo, Badge) {
68 let (raw_msg_info, badge) = self.invoke(|cptr, ipc_buffer| {
69 ipc_buffer.inner_mut().seL4_NBSendRecv(
70 cptr.bits(),
71 info.into_inner(),
72 src.bits(),
73 reply_authority
74 .into_reply_authority()
75 .into_sys_reply_authority(),
76 )
77 });
78 (MessageInfo::from_inner(raw_msg_info), badge)
79 }
80
81 pub fn recv(self, reply_authority: impl ConveysReplyAuthority) -> (MessageInfo, Badge) {
83 let (raw_msg_info, badge) = self.invoke(|cptr, ipc_buffer| {
84 ipc_buffer.inner_mut().seL4_Recv(
85 cptr.bits(),
86 reply_authority
87 .into_reply_authority()
88 .into_sys_reply_authority(),
89 )
90 });
91 (MessageInfo::from_inner(raw_msg_info), badge)
92 }
93
94 pub fn nb_recv(self, reply_authority: impl ConveysReplyAuthority) -> (MessageInfo, Badge) {
96 let (raw_msg_info, badge) = self.invoke(|cptr, ipc_buffer| {
97 ipc_buffer.inner_mut().seL4_NBRecv(
98 cptr.bits(),
99 reply_authority
100 .into_reply_authority()
101 .into_sys_reply_authority(),
102 )
103 });
104 (MessageInfo::from_inner(raw_msg_info), badge)
105 }
106
107 pub fn call(self, info: MessageInfo) -> MessageInfo {
109 MessageInfo::from_inner(self.invoke(|cptr, ipc_buffer| {
110 ipc_buffer
111 .inner_mut()
112 .seL4_Call(cptr.bits(), info.into_inner())
113 }))
114 }
115
116 pub fn reply_recv(
118 self,
119 info: MessageInfo,
120 reply_authority: impl ConveysReplyAuthority,
121 ) -> (MessageInfo, Badge) {
122 let (raw_msg_info, badge) = self.invoke(|cptr, ipc_buffer| {
123 ipc_buffer.inner_mut().seL4_ReplyRecv(
124 cptr.bits(),
125 info.into_inner(),
126 reply_authority
127 .into_reply_authority()
128 .into_sys_reply_authority(),
129 )
130 });
131 (MessageInfo::from_inner(raw_msg_info), badge)
132 }
133
134 pub fn send_with_mrs<M: FastMessages>(self, info: MessageInfo, messages: M) {
135 let [msg0, msg1, msg2, msg3] = messages.prepare_in();
136 self.invoke(|cptr, ipc_buffer| {
137 ipc_buffer.inner_mut().seL4_SendWithMRs(
138 cptr.bits(),
139 info.into_inner(),
140 msg0,
141 msg1,
142 msg2,
143 msg3,
144 )
145 })
146 }
147
148 pub fn recv_with_mrs(self, reply_authority: impl ConveysReplyAuthority) -> RecvWithMRs {
149 let mut msg = [0; NUM_FAST_MESSAGE_REGISTERS];
150 let [mr0, mr1, mr2, mr3] = &mut msg;
151 let (raw_msg_info, badge) = self.invoke(|cptr, ipc_buffer| {
152 ipc_buffer.inner_mut().seL4_RecvWithMRs(
153 cptr.bits(),
154 Some(mr0),
155 Some(mr1),
156 Some(mr2),
157 Some(mr3),
158 reply_authority
159 .into_reply_authority()
160 .into_sys_reply_authority(),
161 )
162 });
163 RecvWithMRs {
164 info: MessageInfo::from_inner(raw_msg_info),
165 badge,
166 msg,
167 }
168 }
169
170 pub fn call_with_mrs<M: FastMessages>(self, info: MessageInfo, messages: M) -> CallWithMRs {
171 let mut msg = messages.prepare_in_out();
172 let [mr0, mr1, mr2, mr3] = &mut msg;
173 let raw_msg_info = self.invoke(|cptr, ipc_buffer| {
174 ipc_buffer.inner_mut().seL4_CallWithMRs(
175 cptr.bits(),
176 info.into_inner(),
177 Some(mr0),
178 Some(mr1),
179 Some(mr2),
180 Some(mr3),
181 )
182 });
183 CallWithMRs {
184 info: MessageInfo::from_inner(raw_msg_info),
185 msg,
186 }
187 }
188}
189
190impl<C: InvocationContext> cap::Notification<C> {
191 pub fn signal(self) {
193 self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_Signal(cptr.bits()))
194 }
195
196 pub fn wait(self) -> (WaitMessageInfo, Badge) {
198 let (info, badge) =
199 self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_Wait(cptr.bits()));
200 (wait_message_info_from_sys(info), badge)
201 }
202
203 pub fn poll(self) -> (MessageInfo, Badge) {
205 let (info, badge) =
206 self.invoke(|cptr, ipc_buffer| ipc_buffer.inner_mut().seL4_Poll(cptr.bits()));
207 (MessageInfo::from_inner(info), badge)
208 }
209}
210
211#[sel4_cfg(not(KERNEL_MCS))]
213pub fn reply(ipc_buffer: &mut IpcBuffer, info: MessageInfo) {
214 ipc_buffer.inner_mut().seL4_Reply(info.into_inner())
215}
216
217pub fn r#yield() {
219 sys::seL4_Yield()
220}
221
222#[sel4_cfg(SET_TLS_BASE_SELF)]
224pub fn set_tls_base(addr: usize) {
225 sys::seL4_SetTLSBase(addr.try_into().unwrap())
226}
227
228const UNUSED_FOR_IN: Word = 0;
231
232pub struct RecvWithMRs {
234 pub info: MessageInfo,
235 pub badge: Badge,
236 pub msg: [Word; NUM_FAST_MESSAGE_REGISTERS],
237}
238
239pub struct CallWithMRs {
241 pub info: MessageInfo,
242 pub msg: [Word; NUM_FAST_MESSAGE_REGISTERS],
243}
244
245type ConcreteFastMessagesForIn = [Option<Word>; NUM_FAST_MESSAGE_REGISTERS];
246
247type ConcreteFastMessagesForInOut = [Word; NUM_FAST_MESSAGE_REGISTERS];
248
249pub trait FastMessages: fast_messages_sealing::FastMessagesSealed {
251 fn prepare_in(self) -> ConcreteFastMessagesForIn;
252
253 fn prepare_in_out(self) -> ConcreteFastMessagesForInOut;
254}
255
256impl<const N: usize> FastMessages for [Word; N]
257where
258 [Word; N]: fast_messages_sealing::FastMessagesSealed,
259{
260 fn prepare_in(self) -> ConcreteFastMessagesForIn {
261 array::from_fn(|i| if i < self.len() { Some(self[i]) } else { None })
262 }
263
264 fn prepare_in_out(self) -> ConcreteFastMessagesForInOut {
265 array::from_fn(|i| {
266 if i < self.len() {
267 self[i]
268 } else {
269 UNUSED_FOR_IN
270 }
271 })
272 }
273}
274
275impl FastMessages for &[Word] {
276 fn prepare_in(self) -> ConcreteFastMessagesForIn {
277 assert!(self.len() <= NUM_FAST_MESSAGE_REGISTERS);
278 array::from_fn(|i| if i < self.len() { Some(self[i]) } else { None })
279 }
280
281 fn prepare_in_out(self) -> ConcreteFastMessagesForInOut {
282 assert!(self.len() <= NUM_FAST_MESSAGE_REGISTERS);
283 array::from_fn(|i| {
284 if i < self.len() {
285 self[i]
286 } else {
287 UNUSED_FOR_IN
288 }
289 })
290 }
291}
292
293mod fast_messages_sealing {
294 use super::Word;
295
296 pub trait FastMessagesSealed {}
297
298 impl FastMessagesSealed for [Word; 0] {}
299 impl FastMessagesSealed for [Word; 1] {}
300 impl FastMessagesSealed for [Word; 2] {}
301 impl FastMessagesSealed for [Word; 3] {}
302 impl FastMessagesSealed for [Word; 4] {}
303
304 impl FastMessagesSealed for &[Word] {}
305}
306
307#[allow(clippy::assertions_on_constants)]
308const _: () = assert!(NUM_FAST_MESSAGE_REGISTERS == 4);