Nothing to see here, move along
1use crate::cap::object::ObjectTag;
2use crate::cap::pool::POOL;
3use crate::cap::table::{CapRef, Rights};
4use crate::ipc::{AlwaysBlocked, IpcOutcome, endpoint, message};
5use crate::proc::context::{IpcMessage, Reply};
6use crate::proc::{BlockedReason, PROCESSES, ProcessState};
7use lancer_core::object_layout::EndpointObject;
8
9crate::kernel_test!(
10 fn reply_recv_delivers_reply_and_receives() {
11 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
12 let mut ptable = PROCESSES.lock();
13
14 let client_created = ptable.allocate(&mut allocator).expect("alloc client");
15 let server_created = ptable.allocate(&mut allocator).expect("alloc server");
16 let sender_created = ptable.allocate(&mut allocator).expect("alloc sender");
17 ptable.start(client_created).expect("start client");
18 ptable.start(server_created).expect("start server");
19 ptable.start(sender_created).expect("start sender");
20 let client_pid = client_created.pid();
21 let server_pid = server_created.pid();
22 let sender_pid = sender_created.pid();
23
24 let (ep_id, ep_gen) =
25 crate::tests::helpers::alloc_endpoint(&mut POOL.lock()).expect("alloc endpoint");
26
27 let cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
28
29 ptable.exec_mut(client_pid).unwrap().ipc_message =
30 IpcMessage::from_regs([0x1111, 0, 0, 0, 0, 0]);
31 ptable.simulate_dispatch(client_pid);
32 ptable.simulate_dispatch(server_pid);
33 let blocked_server = ptable[server_pid]
34 .block_on(BlockedReason::Receiving(ep_id, ep_gen))
35 .expect("block server");
36
37 {
38 let mut pool = POOL.lock();
39 let ep = pool
40 .write_as::<EndpointObject>(ep_id, ep_gen)
41 .expect("get ep");
42 let mut receivers = endpoint::load_receivers(ep);
43 endpoint::enqueue(&mut receivers, blocked_server, &mut ptable).expect("enqueue server");
44 let ep = pool
45 .write_as::<EndpointObject>(ep_id, ep_gen)
46 .expect("get ep for store");
47 endpoint::store_receivers(ep, &receivers);
48 }
49
50 let call_result = endpoint::do_call(&cap, client_pid, &mut ptable);
51 match call_result {
52 Ok(AlwaysBlocked) => {}
53 _ => panic!("expected Blocked from do_call"),
54 }
55
56 assert!(
57 ptable.exec(server_pid).unwrap().reply_target == Some(client_pid),
58 "server should have reply_target set to client"
59 );
60
61 ptable.exec_mut(sender_pid).unwrap().ipc_message =
62 IpcMessage::from_regs([0x2222, 0, 0, 0, 0, 0]);
63 ptable.simulate_dispatch(sender_pid);
64 let sender_blocked = ptable[sender_pid]
65 .block_on(BlockedReason::Sending(ep_id, ep_gen))
66 .expect("block sender");
67
68 {
69 let mut pool = POOL.lock();
70 let ep = pool
71 .write_as::<EndpointObject>(ep_id, ep_gen)
72 .expect("get ep");
73 let mut senders = endpoint::load_senders(ep);
74 endpoint::enqueue(&mut senders, sender_blocked, &mut ptable).expect("enqueue sender");
75 let ep = pool
76 .write_as::<EndpointObject>(ep_id, ep_gen)
77 .expect("get ep for store");
78 endpoint::store_senders(ep, &senders);
79 }
80
81 let full_reply = IpcMessage::<Reply>::from_reply_regs([0xAAAA, 0, 0, 0, 0]).into_full();
82 {
83 let client_exec = ptable.exec_mut(client_pid).unwrap();
84 let proof = unsafe { crate::types::BlockedPid::trust(client_pid) };
85 client_exec.ipc_message = full_reply;
86 message::inject_into_context(&mut client_exec.saved_context, &full_reply);
87 client_exec.saved_context.rax = server_pid.raw() as u64;
88 ptable.unblock_and_enqueue(client_pid, proof).expect("unblock client");
89 }
90 ptable.exec_mut(server_pid).unwrap().reply_target = None;
91
92 let recv_result = endpoint::do_recv(&cap, server_pid, &mut ptable);
93 match recv_result {
94 Ok(IpcOutcome::Done(s)) => {
95 assert!(s == sender_pid, "server should receive from sender");
96 }
97 _ => panic!("expected Done from do_recv after reply"),
98 }
99
100 let _ = POOL.lock().dec_ref_phys(ep_id, ep_gen);
101 ptable.destroy(client_pid, &mut allocator);
102 ptable.destroy(server_pid, &mut allocator);
103 ptable.destroy(sender_pid, &mut allocator);
104 }
105);
106
107crate::kernel_test!(
108 fn reply_recv_rejects_non_calling_target() {
109 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
110 let mut ptable = PROCESSES.lock();
111
112 let server_created = ptable.allocate(&mut allocator).expect("alloc server");
113 let receiver_created = ptable.allocate(&mut allocator).expect("alloc receiver");
114 ptable.start(server_created).expect("start server");
115 ptable.start(receiver_created).expect("start receiver");
116 let server_pid = server_created.pid();
117 let receiver_pid = receiver_created.pid();
118
119 let (ep_id, ep_gen) =
120 crate::tests::helpers::alloc_endpoint(&mut POOL.lock()).expect("alloc endpoint");
121
122 ptable.simulate_dispatch(receiver_pid);
123 let blocked_recv = ptable[receiver_pid]
124 .block_on(BlockedReason::Receiving(ep_id, ep_gen))
125 .expect("block receiver");
126
127 {
128 let mut pool = POOL.lock();
129 let ep = pool
130 .write_as::<EndpointObject>(ep_id, ep_gen)
131 .expect("get ep");
132 let mut receivers = endpoint::load_receivers(ep);
133 endpoint::enqueue(&mut receivers, blocked_recv, &mut ptable).expect("enqueue receiver");
134 let ep = pool
135 .write_as::<EndpointObject>(ep_id, ep_gen)
136 .expect("get ep for store");
137 endpoint::store_receivers(ep, &receivers);
138 }
139
140 ptable.exec_mut(server_pid).unwrap().reply_target = Some(receiver_pid);
141
142 let is_call_target = ptable[receiver_pid].state() == ProcessState::Blocked
143 && matches!(
144 ptable[receiver_pid].blocked_reason(),
145 Some(BlockedReason::Calling(id, _)) if id == ep_id
146 );
147
148 assert!(
149 !is_call_target,
150 "a Receiving process should NOT be accepted as a Calling reply target"
151 );
152
153 let _ = POOL.lock().dec_ref_phys(ep_id, ep_gen);
154 ptable.destroy(server_pid, &mut allocator);
155 ptable.destroy(receiver_pid, &mut allocator);
156 }
157);
158
159crate::kernel_test!(
160 fn reply_recv_invalid_reply_pid() {
161 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
162 let mut ptable = PROCESSES.lock();
163
164 let server_created = ptable.allocate(&mut allocator).expect("alloc server");
165 ptable.start(server_created).expect("start server");
166 let server_pid = server_created.pid();
167
168 let (ep_id, ep_gen) =
169 crate::tests::helpers::alloc_endpoint(&mut POOL.lock()).expect("alloc endpoint");
170
171 ptable.exec_mut(server_pid).unwrap().reply_target = None;
172
173 let reply_pid = crate::types::Pid::try_new(u32::MAX);
174 assert!(reply_pid.is_none(), "Pid::try_new(MAX) should return None");
175
176 let _ = POOL.lock().dec_ref_phys(ep_id, ep_gen);
177 ptable.destroy(server_pid, &mut allocator);
178 }
179);