Nothing to see here, move along
1use crate::cap::cnode;
2use crate::cap::object::ObjectTag;
3use crate::cap::pool::POOL;
4use crate::cap::retype::kernel_retype;
5use crate::cap::table::Rights;
6use crate::error::KernelError;
7use crate::proc::PROCESSES;
8use lancer_core::object_layout::{KernelObject, UntypedObject};
9
10crate::kernel_test!(
11 fn retype_single_endpoint() {
12 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
13 let mut ptable = PROCESSES.lock();
14 let created = ptable.allocate(&mut allocator).expect("alloc");
15 ptable.start(created).expect("start");
16 let pid = created.pid();
17 crate::tests::helpers::bootstrap_test_cnode(pid, &mut ptable);
18
19 let (ut_id, ut_gen, _phys) = crate::tests::helpers::allocate_untyped(&ptable, false);
20
21 let (cnode_id, cnode_gen, depth, gv, gb) =
22 cnode::cnode_coords(pid, &ptable).expect("coords");
23 let dest_slot = 50u64;
24
25 {
26 let mut pool = POOL.lock_after(&ptable);
27 kernel_retype(
28 &mut pool,
29 None,
30 ut_id,
31 ut_gen,
32 ObjectTag::Endpoint,
33 0,
34 cnode_id,
35 cnode_gen,
36 dest_slot,
37 depth,
38 gv,
39 gb,
40 1,
41 )
42 .expect("retype endpoint");
43 }
44
45 {
46 let pool = POOL.lock_after(&ptable);
47 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_slot, depth, gv, gb)
48 .expect("read slot");
49 assert!(cap.tag() == ObjectTag::Endpoint);
50 assert!(cap.rights().contains(Rights::ALL));
51
52 assert!(pool.get_tag(cap.phys(), cap.generation()) == Ok(ObjectTag::Endpoint));
53 }
54
55 ptable.destroy(pid, &mut allocator);
56 }
57);
58
59crate::kernel_test!(
60 fn retype_multiple_endpoints() {
61 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
62 let mut ptable = PROCESSES.lock();
63 let created = ptable.allocate(&mut allocator).expect("alloc");
64 ptable.start(created).expect("start");
65 let pid = created.pid();
66 crate::tests::helpers::bootstrap_test_cnode(pid, &mut ptable);
67
68 let (ut_id, ut_gen, _phys) = crate::tests::helpers::allocate_untyped(&ptable, false);
69 let (cnode_id, cnode_gen, depth, gv, gb) =
70 cnode::cnode_coords(pid, &ptable).expect("coords");
71 let dest_base = 60u64;
72 let count = 3u32;
73
74 {
75 let mut pool = POOL.lock_after(&ptable);
76 kernel_retype(
77 &mut pool,
78 None,
79 ut_id,
80 ut_gen,
81 ObjectTag::Endpoint,
82 0,
83 cnode_id,
84 cnode_gen,
85 dest_base,
86 depth,
87 gv,
88 gb,
89 count,
90 )
91 .expect("retype 3 endpoints");
92 }
93
94 {
95 let pool = POOL.lock_after(&ptable);
96 (0..count as u64).for_each(|i| {
97 let cap = cnode::resolve_and_read(
98 &pool,
99 cnode_id,
100 cnode_gen,
101 dest_base + i,
102 depth,
103 gv,
104 gb,
105 )
106 .expect("read slot");
107 assert!(cap.tag() == ObjectTag::Endpoint);
108 assert!(cap.rights().contains(Rights::ALL));
109 });
110 }
111
112 ptable.destroy(pid, &mut allocator);
113 }
114);
115
116crate::kernel_test!(
117 fn retype_exceeds_capacity_fails() {
118 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
119 let mut ptable = PROCESSES.lock();
120 let created = ptable.allocate(&mut allocator).expect("alloc");
121 ptable.start(created).expect("start");
122 let pid = created.pid();
123 crate::tests::helpers::bootstrap_test_cnode(pid, &mut ptable);
124
125 let small_size_bits = 12u8;
126 let small_frames = 1usize;
127 let phys_base = crate::mem::phys::BitmapFrameAllocator
128 .allocate_contiguous(small_frames)
129 .expect("alloc small untyped");
130 let base_virt = crate::mem::addr::phys_to_virt(phys_base);
131 unsafe {
132 core::ptr::write_bytes(base_virt.as_mut_ptr::<u8>(), 0, small_frames * 4096);
133 }
134 let header = lancer_core::header::KernelObjectHeader::new(ObjectTag::Untyped, 0, 64);
135 let mut ut_obj = UntypedObject::init_default(header);
136 ut_obj.phys_base = phys_base.as_u64();
137 ut_obj.size_bits = small_size_bits;
138 ut_obj.is_device = 0;
139 let ut_phys = crate::cap::kernel_objects::alloc_slot().expect("alloc ut slot");
140 crate::cap::kernel_objects::write_at(ut_phys, ut_obj);
141 let (ut_id, ut_gen) = POOL
142 .lock_after(&ptable)
143 .register_object(ut_phys, ObjectTag::Untyped)
144 .expect("register ut");
145
146 let (cnode_id, cnode_gen, depth, gv, gb) =
147 cnode::cnode_coords(pid, &ptable).expect("coords");
148
149 let result = {
150 let mut pool = POOL.lock_after(&ptable);
151 kernel_retype(
152 &mut pool,
153 None,
154 ut_id,
155 ut_gen,
156 ObjectTag::Endpoint,
157 0,
158 cnode_id,
159 cnode_gen,
160 70,
161 depth,
162 gv,
163 gb,
164 100,
165 )
166 };
167 assert!(result.is_err(), "retype exceeding capacity must fail");
168
169 {
170 let pool = POOL.lock_after(&ptable);
171 let ut = pool
172 .read_as::<UntypedObject>(ut_id, ut_gen)
173 .expect("read ut");
174 assert!(ut.watermark == 0, "watermark must be unchanged on failure");
175 }
176
177 ptable.destroy(pid, &mut allocator);
178 }
179);
180
181crate::kernel_test!(
182 fn retype_occupied_slot_rolls_back() {
183 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
184 let mut ptable = PROCESSES.lock();
185 let created = ptable.allocate(&mut allocator).expect("alloc");
186 ptable.start(created).expect("start");
187 let pid = created.pid();
188 crate::tests::helpers::bootstrap_test_cnode(pid, &mut ptable);
189
190 let (ut_id, ut_gen, _phys) = crate::tests::helpers::allocate_untyped(&ptable, false);
191 let (cnode_id, cnode_gen, depth, gv, gb) =
192 cnode::cnode_coords(pid, &ptable).expect("coords");
193
194 let occupied_slot = 80u64;
195 {
196 let mut pool = POOL.lock_after(&ptable);
197 kernel_retype(
198 &mut pool,
199 None,
200 ut_id,
201 ut_gen,
202 ObjectTag::Endpoint,
203 0,
204 cnode_id,
205 cnode_gen,
206 occupied_slot,
207 depth,
208 gv,
209 gb,
210 1,
211 )
212 .expect("first retype");
213 }
214
215 let watermark_before = {
216 let pool = POOL.lock_after(&ptable);
217 pool.read_as::<UntypedObject>(ut_id, ut_gen)
218 .expect("read ut")
219 .watermark
220 };
221
222 let result = {
223 let mut pool = POOL.lock_after(&ptable);
224 kernel_retype(
225 &mut pool,
226 None,
227 ut_id,
228 ut_gen,
229 ObjectTag::Notification,
230 0,
231 cnode_id,
232 cnode_gen,
233 occupied_slot,
234 depth,
235 gv,
236 gb,
237 1,
238 )
239 };
240 assert!(
241 matches!(result, Err(KernelError::SlotOccupied)),
242 "retype into occupied slot must fail"
243 );
244
245 {
246 let pool = POOL.lock_after(&ptable);
247 let cap =
248 cnode::resolve_and_read(&pool, cnode_id, cnode_gen, occupied_slot, depth, gv, gb)
249 .expect("read slot");
250 assert!(
251 cap.tag() == ObjectTag::Endpoint,
252 "original cap must survive"
253 );
254
255 let ut = pool
256 .read_as::<UntypedObject>(ut_id, ut_gen)
257 .expect("read ut");
258 assert!(
259 ut.watermark == watermark_before,
260 "watermark must not advance on rollback"
261 );
262 }
263
264 ptable.destroy(pid, &mut allocator);
265 }
266);
267
268crate::kernel_test!(
269 fn retype_stale_generation_fails() {
270 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
271 let mut ptable = PROCESSES.lock();
272 let created = ptable.allocate(&mut allocator).expect("alloc");
273 ptable.start(created).expect("start");
274 let pid = created.pid();
275 crate::tests::helpers::bootstrap_test_cnode(pid, &mut ptable);
276
277 let (ut_id, ut_gen, _phys) = crate::tests::helpers::allocate_untyped(&ptable, false);
278 let (cnode_id, cnode_gen, depth, gv, gb) =
279 cnode::cnode_coords(pid, &ptable).expect("coords");
280
281 let stale_gen = crate::types::Generation::new(ut_gen.raw().wrapping_add(1));
282
283 let result = {
284 let mut pool = POOL.lock_after(&ptable);
285 kernel_retype(
286 &mut pool,
287 None,
288 ut_id,
289 stale_gen,
290 ObjectTag::Endpoint,
291 0,
292 cnode_id,
293 cnode_gen,
294 90,
295 depth,
296 gv,
297 gb,
298 1,
299 )
300 };
301 assert!(result.is_err(), "retype with stale generation must fail");
302
303 ptable.destroy(pid, &mut allocator);
304 }
305);
306
307crate::kernel_test!(
308 fn device_untyped_rejects_non_frame() {
309 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
310 let mut ptable = PROCESSES.lock();
311 let created = ptable.allocate(&mut allocator).expect("alloc");
312 ptable.start(created).expect("start");
313 let pid = created.pid();
314 crate::tests::helpers::bootstrap_test_cnode(pid, &mut ptable);
315
316 let (ut_id, ut_gen, _phys) = crate::tests::helpers::allocate_untyped(&ptable, true);
317 let (cnode_id, cnode_gen, depth, gv, gb) =
318 cnode::cnode_coords(pid, &ptable).expect("coords");
319
320 let result = {
321 let mut pool = POOL.lock_after(&ptable);
322 kernel_retype(
323 &mut pool,
324 None,
325 ut_id,
326 ut_gen,
327 ObjectTag::Endpoint,
328 0,
329 cnode_id,
330 cnode_gen,
331 100,
332 depth,
333 gv,
334 gb,
335 1,
336 )
337 };
338 assert!(
339 matches!(result, Err(KernelError::InvalidType)),
340 "device untyped must reject non-Frame retype"
341 );
342
343 ptable.destroy(pid, &mut allocator);
344 }
345);