Nothing to see here, move along meow
1use crate::cap::cnode;
2use crate::cap::frame_table::FRAME_TABLE;
3use crate::cap::pool::POOL;
4use crate::cap::retype::kernel_retype;
5use crate::cap::table::Rights;
6use crate::proc::PROCESSES;
7use crate::tests::helpers;
8use lancer_core::header::NONE_SENTINEL;
9use lancer_core::object_layout::FrameObject;
10use lancer_core::object_tag::ObjectTag;
11
12crate::kernel_test!(
13 fn frame_retype_from_untyped() {
14 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
15 let mut ptable = PROCESSES.lock();
16 let created = ptable.allocate(&mut allocator).expect("alloc");
17 ptable.start(created).expect("start");
18 let pid = created.pid();
19 helpers::bootstrap_test_cnode(pid, &mut ptable);
20
21 let (ut_id, ut_gen, phys_base) = helpers::allocate_untyped(&ptable, false);
22 let (cnode_id, cnode_gen, depth, gv, gb) =
23 cnode::cnode_coords(pid, &ptable).expect("coords");
24 let dest_slot = 50u64;
25
26 {
27 let mut pool = POOL.lock_after(&ptable);
28 kernel_retype(
29 &mut pool,
30 None,
31 ut_id,
32 ut_gen,
33 ObjectTag::Frame,
34 12,
35 cnode_id,
36 cnode_gen,
37 dest_slot,
38 depth,
39 gv,
40 gb,
41 1,
42 )
43 .expect("retype frame");
44 }
45
46 {
47 let pool = POOL.lock_after(&ptable);
48 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_slot, depth, gv, gb)
49 .expect("read slot");
50 assert!(cap.tag() == ObjectTag::Frame);
51 assert!(cap.rights().contains(Rights::ALL));
52
53 let frame = pool
54 .read_as::<FrameObject>(cap.phys(), cap.generation())
55 .expect("read frame");
56 assert!(frame.phys_addr >= phys_base.as_u64());
57 assert!(frame.header.parent_untyped != NONE_SENTINEL);
58 let ft = FRAME_TABLE.lock();
59 assert!(ft.get(frame.frame_table_idx).mapping_count() == 0);
60 assert!(ft.get(frame.frame_table_idx).iommu_mapping().is_none());
61 }
62
63 ptable.destroy(pid, &mut allocator);
64 }
65);
66
67crate::kernel_test!(
68 fn frame_retype_marks_bitmap() {
69 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
70 let mut ptable = PROCESSES.lock();
71 let created = ptable.allocate(&mut allocator).expect("alloc");
72 ptable.start(created).expect("start");
73 let pid = created.pid();
74 helpers::bootstrap_test_cnode(pid, &mut ptable);
75
76 let (ut_id, ut_gen, _phys_base) = helpers::allocate_untyped(&ptable, false);
77 let (cnode_id, cnode_gen, depth, gv, gb) =
78 cnode::cnode_coords(pid, &ptable).expect("coords");
79
80 {
81 let mut pool = POOL.lock_after(&ptable);
82 kernel_retype(
83 &mut pool,
84 None,
85 ut_id,
86 ut_gen,
87 ObjectTag::Frame,
88 12,
89 cnode_id,
90 cnode_gen,
91 55,
92 depth,
93 gv,
94 gb,
95 1,
96 )
97 .expect("retype frame");
98 }
99
100 {
101 let pool = POOL.lock_after(&ptable);
102 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 55, depth, gv, gb)
103 .expect("read slot");
104 let frame = pool
105 .read_as::<FrameObject>(cap.phys(), cap.generation())
106 .expect("read frame");
107 let frame_idx = (frame.phys_addr / 4096) as usize;
108 assert!(
109 crate::mem::phys::BitmapFrameAllocator::is_used(frame_idx),
110 "frame must be marked used in bitmap"
111 );
112 }
113
114 ptable.destroy(pid, &mut allocator);
115 }
116);
117
118crate::kernel_test!(
119 fn frame_retype_multiple() {
120 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
121 let mut ptable = PROCESSES.lock();
122 let created = ptable.allocate(&mut allocator).expect("alloc");
123 ptable.start(created).expect("start");
124 let pid = created.pid();
125 helpers::bootstrap_test_cnode(pid, &mut ptable);
126
127 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false);
128 let (cnode_id, cnode_gen, depth, gv, gb) =
129 cnode::cnode_coords(pid, &ptable).expect("coords");
130 let dest_base = 60u64;
131 let count = 4u32;
132
133 {
134 let mut pool = POOL.lock_after(&ptable);
135 kernel_retype(
136 &mut pool,
137 None,
138 ut_id,
139 ut_gen,
140 ObjectTag::Frame,
141 12,
142 cnode_id,
143 cnode_gen,
144 dest_base,
145 depth,
146 gv,
147 gb,
148 count,
149 )
150 .expect("retype 4 frames");
151 }
152
153 {
154 let pool = POOL.lock_after(&ptable);
155 let addrs: [u64; 4] = core::array::from_fn(|i| {
156 let cap = cnode::resolve_and_read(
157 &pool,
158 cnode_id,
159 cnode_gen,
160 dest_base + i as u64,
161 depth,
162 gv,
163 gb,
164 )
165 .expect("read slot");
166 assert!(cap.tag() == ObjectTag::Frame);
167 pool.read_as::<FrameObject>(cap.phys(), cap.generation())
168 .expect("read frame")
169 .phys_addr
170 });
171
172 (0..4).for_each(|i| {
173 (i + 1..4).for_each(|j| {
174 assert!(
175 addrs[i] != addrs[j],
176 "frames {} and {} have same phys addr {:#x}",
177 i,
178 j,
179 addrs[i]
180 );
181 });
182 });
183
184 (0..3).for_each(|i| {
185 assert!(
186 addrs[i + 1] == addrs[i] + 4096,
187 "expected 4KB stride between frames {} and {}",
188 i,
189 i + 1
190 );
191 });
192 }
193
194 ptable.destroy(pid, &mut allocator);
195 }
196);
197
198crate::kernel_test!(
199 fn device_untyped_allows_frame_retype() {
200 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
201 let mut ptable = PROCESSES.lock();
202 let created = ptable.allocate(&mut allocator).expect("alloc");
203 ptable.start(created).expect("start");
204 let pid = created.pid();
205 helpers::bootstrap_test_cnode(pid, &mut ptable);
206
207 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, true);
208 let (cnode_id, cnode_gen, depth, gv, gb) =
209 cnode::cnode_coords(pid, &ptable).expect("coords");
210
211 {
212 let mut pool = POOL.lock_after(&ptable);
213 kernel_retype(
214 &mut pool,
215 None,
216 ut_id,
217 ut_gen,
218 ObjectTag::Frame,
219 12,
220 cnode_id,
221 cnode_gen,
222 100,
223 depth,
224 gv,
225 gb,
226 1,
227 )
228 .expect("device untyped must allow Frame retype");
229 }
230
231 {
232 let pool = POOL.lock_after(&ptable);
233 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 100, depth, gv, gb)
234 .expect("read slot");
235 assert!(cap.tag() == ObjectTag::Frame);
236 }
237
238 ptable.destroy(pid, &mut allocator);
239 }
240);
241
242crate::kernel_test!(
243 fn frame_cleanup_unmaps_processes() {
244 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
245 let mut ptable = PROCESSES.lock();
246 let created = ptable.allocate(&mut allocator).expect("alloc");
247 ptable.start(created).expect("start");
248 let pid = created.pid();
249 helpers::bootstrap_test_cnode(pid, &mut ptable);
250
251 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false);
252 let (cnode_id, cnode_gen, depth, gv, gb) =
253 cnode::cnode_coords(pid, &ptable).expect("coords");
254
255 {
256 let mut pool = POOL.lock_after(&ptable);
257 kernel_retype(
258 &mut pool,
259 None,
260 ut_id,
261 ut_gen,
262 ObjectTag::Frame,
263 12,
264 cnode_id,
265 cnode_gen,
266 110,
267 depth,
268 gv,
269 gb,
270 1,
271 )
272 .expect("retype frame");
273 }
274
275 let (frame_obj_id, frame_gen, ft_idx) = {
276 let pool = POOL.lock_after(&ptable);
277 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 110, depth, gv, gb)
278 .expect("read slot");
279 let frame = pool
280 .read_as::<FrameObject>(cap.phys(), cap.generation())
281 .expect("read frame for idx");
282 (cap.phys(), cap.generation(), frame.frame_table_idx)
283 };
284
285 {
286 let vaddr = x86_64::VirtAddr::new(0x40_0000);
287 FRAME_TABLE
288 .lock()
289 .get_mut(ft_idx)
290 .add_mapping(pid, vaddr)
291 .expect("add mapping");
292 assert!(FRAME_TABLE.lock().get(ft_idx).mapping_count() > 0);
293 }
294
295 {
296 let (_new_gen, freed) = POOL
297 .lock_after(&ptable)
298 .revoke_phys(frame_obj_id, frame_gen)
299 .expect("revoke");
300 freed.inspect(|(phys, tag)| {
301 crate::cap::ops::cleanup_by_tag_with_ptable(
302 *tag,
303 *phys,
304 &mut ptable,
305 );
306 });
307 }
308
309 ptable.destroy(pid, &mut allocator);
310 }
311);
312
313crate::kernel_test!(
314 fn frame_from_untyped_not_freed_to_bitmap() {
315 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
316 let mut ptable = PROCESSES.lock();
317 let created = ptable.allocate(&mut allocator).expect("alloc");
318 ptable.start(created).expect("start");
319 let pid = created.pid();
320 helpers::bootstrap_test_cnode(pid, &mut ptable);
321
322 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false);
323 let (cnode_id, cnode_gen, depth, gv, gb) =
324 cnode::cnode_coords(pid, &ptable).expect("coords");
325
326 {
327 let mut pool = POOL.lock_after(&ptable);
328 kernel_retype(
329 &mut pool,
330 None,
331 ut_id,
332 ut_gen,
333 ObjectTag::Frame,
334 12,
335 cnode_id,
336 cnode_gen,
337 120,
338 depth,
339 gv,
340 gb,
341 1,
342 )
343 .expect("retype frame");
344 }
345
346 let frame_phys = {
347 let pool = POOL.lock_after(&ptable);
348 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 120, depth, gv, gb)
349 .expect("read slot");
350 pool.read_as::<FrameObject>(cap.phys(), cap.generation())
351 .expect("read frame")
352 .phys_addr
353 };
354
355 let frame_idx = (frame_phys / 4096) as usize;
356 assert!(
357 crate::mem::phys::BitmapFrameAllocator::is_used(frame_idx),
358 "frame must be used before revoke"
359 );
360
361 let (frame_obj_id, frame_gen) = {
362 let pool = POOL.lock_after(&ptable);
363 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 120, depth, gv, gb)
364 .expect("read slot");
365 (cap.phys(), cap.generation())
366 };
367
368 {
369 let (_new_gen, freed) = POOL
370 .lock_after(&ptable)
371 .revoke_phys(frame_obj_id, frame_gen)
372 .expect("revoke");
373 freed.inspect(|(phys, tag)| {
374 crate::cap::ops::cleanup_by_tag_with_ptable(
375 *tag,
376 *phys,
377 &mut ptable,
378 );
379 });
380 }
381
382 assert!(
383 crate::mem::phys::BitmapFrameAllocator::is_used(frame_idx),
384 "frame from untyped must still be marked used after revoke"
385 );
386
387 ptable.destroy(pid, &mut allocator);
388 }
389);