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