Nothing to see here, move along
1use crate::cap::cnode;
2use crate::cap::object::{EndpointData, ObjectData, ObjectTag};
3use crate::cap::pool::POOL;
4use crate::cap::table::{CapRef, CapSlot, Rights};
5use crate::error::KernelError;
6use crate::mem::phys::BitmapFrameAllocator;
7use crate::proc::PROCESSES;
8
9fn bootstrap_test_cnode(pid: crate::types::Pid, ptable: &mut crate::proc::ProcessManager) {
10 let size_bits = crate::proc::ROOT_CNODE_SIZE_BITS;
11 let allocator = &BitmapFrameAllocator;
12 let cnode_data = cnode::create_cnode(size_bits, allocator).expect("create cnode");
13 let frame_count = cnode_data.frame_count;
14 let (cnode_id, cnode_gen) = POOL
15 .lock()
16 .allocate(ObjectData::CNode(cnode_data))
17 .expect("alloc cnode");
18 let proc = ptable.get_mut(pid).expect("get proc");
19 proc.root_cnode = Some((cnode_id, cnode_gen));
20 proc.cnode_depth = size_bits;
21 proc.charge_frames(frame_count as u16).expect("charge frames");
22}
23
24crate::kernel_test!(
25 fn cnode_create_and_destroy() {
26 let allocator = &BitmapFrameAllocator;
27 let cnode_data = cnode::create_cnode(4, allocator).expect("create cnode");
28 assert!(cnode_data.size_bits == 4);
29 assert!(cnode_data.frame_count > 0);
30 cnode::destroy_cnode(&cnode_data, allocator);
31 }
32);
33
34crate::kernel_test!(
35 fn cnode_create_invalid_size_rejected() {
36 let allocator = &BitmapFrameAllocator;
37 assert!(matches!(
38 cnode::create_cnode(0, allocator),
39 Err(KernelError::InvalidParameter)
40 ));
41 assert!(matches!(
42 cnode::create_cnode(13, allocator),
43 Err(KernelError::InvalidParameter)
44 ));
45 }
46);
47
48crate::kernel_test!(
49 fn single_level_resolve_insert_read() {
50 let allocator = &BitmapFrameAllocator;
51 let cnode_data = cnode::create_cnode(4, allocator).expect("create");
52 let (cid, cgen) = POOL
53 .lock()
54 .allocate(ObjectData::CNode(cnode_data))
55 .expect("alloc");
56
57 let (ep_id, ep_gen) = POOL
58 .lock()
59 .allocate(ObjectData::Endpoint(EndpointData::new()))
60 .expect("alloc ep");
61 let cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
62
63 {
64 let pool = POOL.lock();
65 cnode::resolve_and_insert(&pool, cid, cgen, 5, 4, cap).expect("insert");
66 }
67
68 {
69 let pool = POOL.lock();
70 let read = cnode::resolve_and_read(&pool, cid, cgen, 5, 4).expect("read");
71 assert!(read.tag() == ObjectTag::Endpoint);
72 assert!(read.object_id() == ep_id);
73 }
74
75 {
76 let pool = POOL.lock();
77 let slot = cnode::resolve(&pool, cid, cgen, 0, 4).expect("empty slot");
78 assert!(matches!(slot, CapSlot::Empty));
79 }
80
81 {
82 let mut pool = POOL.lock();
83 pool.dec_ref(ep_id, ep_gen);
84 pool.dec_ref(cid, cgen);
85 }
86 }
87);
88
89crate::kernel_test!(
90 fn two_level_resolve() {
91 let allocator = &BitmapFrameAllocator;
92
93 let inner_data = cnode::create_cnode(4, allocator).expect("inner cnode");
94 let (inner_id, inner_gen) = POOL
95 .lock()
96 .allocate(ObjectData::CNode(inner_data))
97 .expect("alloc inner");
98
99 let outer_data = cnode::create_cnode(4, allocator).expect("outer cnode");
100 let (outer_id, outer_gen) = POOL
101 .lock()
102 .allocate(ObjectData::CNode(outer_data))
103 .expect("alloc outer");
104
105 let inner_cap = CapRef::new(ObjectTag::CNode, inner_id, Rights::ALL, inner_gen);
106 {
107 let pool = POOL.lock();
108 cnode::resolve_and_insert(&pool, outer_id, outer_gen, 3, 4, inner_cap)
109 .expect("insert inner cnode at slot 3");
110 }
111
112 let (ep_id, ep_gen) = POOL
113 .lock()
114 .allocate(ObjectData::Endpoint(EndpointData::new()))
115 .expect("alloc ep");
116 let ep_cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
117
118 let address: u64 = (3 << 4) | 7;
119 {
120 let pool = POOL.lock();
121 cnode::resolve_and_insert(&pool, outer_id, outer_gen, address, 8, ep_cap)
122 .expect("insert ep at two-level address");
123 }
124
125 {
126 let pool = POOL.lock();
127 let read = cnode::resolve_and_read(&pool, outer_id, outer_gen, address, 8)
128 .expect("two-level read");
129 assert!(read.tag() == ObjectTag::Endpoint);
130 assert!(read.object_id() == ep_id);
131 }
132
133 {
134 let mut pool = POOL.lock();
135 pool.dec_ref(ep_id, ep_gen);
136 let _ = cnode::resolve_and_clear(&pool, outer_id, outer_gen, 3, 4);
137 pool.dec_ref(inner_id, inner_gen);
138 pool.dec_ref(outer_id, outer_gen);
139 }
140 }
141);
142
143crate::kernel_test!(
144 fn resolve_empty_slot_fails() {
145 let allocator = &BitmapFrameAllocator;
146 let cnode_data = cnode::create_cnode(4, allocator).expect("create");
147 let (cid, cgen) = POOL
148 .lock()
149 .allocate(ObjectData::CNode(cnode_data))
150 .expect("alloc");
151
152 {
153 let pool = POOL.lock();
154 let result = cnode::resolve_and_read(&pool, cid, cgen, 0, 4);
155 assert!(matches!(result, Err(KernelError::SlotEmpty)));
156 }
157
158 POOL.lock().dec_ref(cid, cgen);
159 }
160);
161
162crate::kernel_test!(
163 fn resolve_non_cnode_in_path_fails() {
164 let allocator = &BitmapFrameAllocator;
165 let cnode_data = cnode::create_cnode(4, allocator).expect("create");
166 let (cid, cgen) = POOL
167 .lock()
168 .allocate(ObjectData::CNode(cnode_data))
169 .expect("alloc");
170
171 let (ep_id, ep_gen) = POOL
172 .lock()
173 .allocate(ObjectData::Endpoint(EndpointData::new()))
174 .expect("alloc ep");
175 let ep_cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
176
177 {
178 let pool = POOL.lock();
179 cnode::resolve_and_insert(&pool, cid, cgen, 2, 4, ep_cap).expect("insert ep");
180 }
181
182 let address: u64 = (2 << 4) | 5;
183 {
184 let pool = POOL.lock();
185 let result = cnode::resolve_and_read(&pool, cid, cgen, address, 8);
186 assert!(matches!(result, Err(KernelError::InvalidSlot)));
187 }
188
189 {
190 let mut pool = POOL.lock();
191 pool.dec_ref(ep_id, ep_gen);
192 pool.dec_ref(cid, cgen);
193 }
194 }
195);
196
197crate::kernel_test!(
198 fn stale_generation_rejected() {
199 let allocator = &BitmapFrameAllocator;
200 let cnode_data = cnode::create_cnode(4, allocator).expect("create");
201 let (cid, cgen) = POOL
202 .lock()
203 .allocate(ObjectData::CNode(cnode_data))
204 .expect("alloc");
205
206 let stale_gen = cgen;
207 {
208 let mut pool = POOL.lock();
209 let _ = pool.revoke(cid, cgen);
210 }
211
212 {
213 let pool = POOL.lock();
214 let result = cnode::resolve(&pool, cid, stale_gen, 0, 4);
215 assert!(matches!(result, Err(KernelError::StaleGeneration)));
216 }
217
218 POOL.lock().dec_ref(cid, stale_gen.wrapping_inc());
219 }
220);
221
222crate::kernel_test!(
223 fn invalidate_stale_across_cnode() {
224 let allocator = &BitmapFrameAllocator;
225 let cnode_data = cnode::create_cnode(4, allocator).expect("create");
226 let (cid, cgen) = POOL
227 .lock()
228 .allocate(ObjectData::CNode(cnode_data))
229 .expect("alloc");
230
231 let (ep_id, ep_gen) = POOL
232 .lock()
233 .allocate(ObjectData::Endpoint(EndpointData::new()))
234 .expect("alloc ep");
235 let cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
236
237 {
238 let pool = POOL.lock();
239 cnode::resolve_and_insert(&pool, cid, cgen, 1, 4, cap).expect("insert");
240 }
241 POOL.lock().inc_ref(ep_id, ep_gen).expect("inc ref");
242 {
243 let pool = POOL.lock();
244 cnode::resolve_and_insert(&pool, cid, cgen, 7, 4, cap).expect("insert 2");
245 }
246
247 {
248 let pool = POOL.lock();
249 cnode::invalidate_stale_in_cnode(&pool, cid, cgen, ep_id, ep_gen)
250 .expect("invalidate");
251 }
252
253 {
254 let pool = POOL.lock();
255 let slot1 = cnode::resolve(&pool, cid, cgen, 1, 4).expect("check 1");
256 let slot7 = cnode::resolve(&pool, cid, cgen, 7, 4).expect("check 7");
257 assert!(matches!(slot1, CapSlot::Empty));
258 assert!(matches!(slot7, CapSlot::Empty));
259 }
260
261 {
262 let mut pool = POOL.lock();
263 pool.dec_ref(ep_id, ep_gen);
264 pool.dec_ref(cid, cgen);
265 }
266 }
267);
268
269crate::kernel_test!(
270 fn drain_cnode_tree_cleans_all() {
271 let mut allocator = BitmapFrameAllocator;
272 let mut ptable = PROCESSES.lock();
273 let created = ptable.allocate(&mut allocator).expect("alloc");
274 ptable.start(created).expect("start");
275 let pid = created.pid();
276 bootstrap_test_cnode(pid, &mut ptable);
277
278 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
279
280 (0..3u64).for_each(|i| {
281 let (eid, egen) = POOL
282 .lock_after(&ptable)
283 .allocate(ObjectData::Endpoint(EndpointData::new()))
284 .expect("alloc ep");
285 let cap = CapRef::new(ObjectTag::Endpoint, eid, Rights::ALL, egen);
286 let pool = POOL.lock_after(&ptable);
287 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, i, depth, cap)
288 .expect("insert");
289 });
290
291 let mut drained_count = 0u32;
292 {
293 let mut pool = POOL.lock_after(&ptable);
294 cnode::drain_cnode_tree(&mut pool, cnode_id, cnode_gen, &mut |cap, pool| {
295 pool.dec_ref(cap.object_id(), cap.generation());
296 drained_count += 1;
297 })
298 .expect("drain");
299 }
300 assert!(
301 drained_count == 3,
302 "expected 3 drained caps, got {}",
303 drained_count
304 );
305
306 {
307 let pool = POOL.lock_after(&ptable);
308 let slot0 = cnode::resolve(&pool, cnode_id, cnode_gen, 0, depth).expect("slot0");
309 assert!(matches!(slot0, CapSlot::Empty));
310 }
311
312 ptable.destroy(pid, &mut allocator);
313 }
314);
315
316crate::kernel_test!(
317 fn thread_shares_parent_cnode() {
318 let mut allocator = BitmapFrameAllocator;
319 let mut ptable = PROCESSES.lock();
320
321 let parent_created = ptable.allocate(&mut allocator).expect("alloc parent");
322 ptable.start(parent_created).expect("start parent");
323 let parent_pid = parent_created.pid();
324 bootstrap_test_cnode(parent_pid, &mut ptable);
325
326 let parent_cnode = ptable.get(parent_pid).expect("get parent").root_cnode();
327
328 let child_created = ptable.allocate_thread(parent_pid, &mut allocator).expect("alloc thread");
329 let child_pid = child_created.pid();
330
331 let child_cnode = ptable.get(child_pid).expect("get child").root_cnode();
332
333 assert!(
334 parent_cnode == child_cnode,
335 "thread must share parent's root CNode"
336 );
337 assert!(
338 child_cnode.is_some(),
339 "thread must have a root CNode"
340 );
341
342 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(parent_pid, &ptable).expect("coords");
343 let (ep_id, ep_gen) = POOL
344 .lock_after(&ptable)
345 .allocate(ObjectData::Endpoint(EndpointData::new()))
346 .expect("alloc ep");
347 let cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
348 {
349 let pool = POOL.lock_after(&ptable);
350 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, 5, depth, cap)
351 .expect("insert via parent");
352 }
353
354 {
355 let (child_cid, child_cgen, child_depth) =
356 cnode::cnode_coords(child_pid, &ptable).expect("child coords");
357 let pool = POOL.lock_after(&ptable);
358 let read = cnode::resolve_and_read(&pool, child_cid, child_cgen, 5, child_depth)
359 .expect("read via child");
360 assert!(read.tag() == ObjectTag::Endpoint);
361 assert!(read.object_id() == ep_id);
362 }
363
364 ptable.destroy(child_pid, &mut allocator);
365 ptable.destroy(parent_pid, &mut allocator);
366 }
367);