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