Nothing to see here, move along
at main 345 lines 11 kB view raw
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);