Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 20 kB View raw
1use crate::cap::cnode; 2use crate::cap::pool::POOL; 3use crate::cap::retype::kernel_retype; 4use crate::cap::table::Rights; 5use crate::mem::phys::BitmapFrameAllocator; 6use crate::proc::PROCESSES; 7use crate::proc::address_space::{self, PageAccess}; 8use crate::tests::helpers; 9use lancer_core::header::NONE_SENTINEL; 10use lancer_core::object_layout::VRegionObject; 11use lancer_core::object_tag::ObjectTag; 12use x86_64::PhysAddr; 13use x86_64::structures::paging::PhysFrame; 14 15crate::kernel_test!( 16 fn vregion_retype_from_untyped() { 17 let mut allocator = BitmapFrameAllocator; 18 let mut ptable = PROCESSES.lock(); 19 let created = ptable.allocate(&mut allocator).expect("alloc"); 20 ptable.start(created).expect("start"); 21 let pid = created.pid(); 22 helpers::bootstrap_test_cnode(pid, &mut ptable); 23 24 let (ut_id, ut_gen, phys_base) = helpers::allocate_untyped(&ptable, false); 25 let (cnode_id, cnode_gen, depth, gv, gb) = 26 cnode::cnode_coords(pid, &ptable).expect("coords"); 27 let dest_slot = 50u64; 28 let page_count = 4u16; 29 30 { 31 let mut pool = POOL.lock_after(&ptable); 32 kernel_retype( 33 &mut pool, 34 None, 35 ut_id, 36 ut_gen, 37 ObjectTag::VRegion, 38 0, 39 cnode_id, 40 cnode_gen, 41 dest_slot, 42 depth, 43 gv, 44 gb, 45 page_count as u32, 46 ) 47 .expect("retype vregion"); 48 } 49 50 { 51 let pool = POOL.lock_after(&ptable); 52 let cap = 53 cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_slot, depth, gv, gb) 54 .expect("read slot"); 55 assert!(cap.tag() == ObjectTag::VRegion); 56 assert!(cap.rights().contains(Rights::ALL)); 57 58 let vr = pool 59 .read_as::<VRegionObject>(cap.phys(), cap.generation()) 60 .expect("read vregion"); 61 assert!(vr.phys_base >= phys_base.as_u64()); 62 assert!(vr.page_count == page_count); 63 assert!(vr.owner_pid == NONE_SENTINEL); 64 assert!(vr.child_pid == NONE_SENTINEL); 65 assert!(vr.header.parent_untyped != NONE_SENTINEL); 66 } 67 68 ptable.destroy(pid, &mut allocator); 69 } 70); 71 72crate::kernel_test!( 73 fn vregion_retype_marks_bitmap() { 74 let mut allocator = BitmapFrameAllocator; 75 let mut ptable = PROCESSES.lock(); 76 let created = ptable.allocate(&mut allocator).expect("alloc"); 77 ptable.start(created).expect("start"); 78 let pid = created.pid(); 79 helpers::bootstrap_test_cnode(pid, &mut ptable); 80 81 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false); 82 let (cnode_id, cnode_gen, depth, gv, gb) = 83 cnode::cnode_coords(pid, &ptable).expect("coords"); 84 let page_count = 8u16; 85 86 { 87 let mut pool = POOL.lock_after(&ptable); 88 kernel_retype( 89 &mut pool, 90 None, 91 ut_id, 92 ut_gen, 93 ObjectTag::VRegion, 94 0, 95 cnode_id, 96 cnode_gen, 97 55, 98 depth, 99 gv, 100 gb, 101 page_count as u32, 102 ) 103 .expect("retype vregion"); 104 } 105 106 { 107 let pool = POOL.lock_after(&ptable); 108 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 55, depth, gv, gb) 109 .expect("read slot"); 110 let vr = pool 111 .read_as::<VRegionObject>(cap.phys(), cap.generation()) 112 .expect("read vregion"); 113 114 (0..page_count as u64).for_each(|i| { 115 let frame_idx = ((vr.phys_base + i * 4096) / 4096) as usize; 116 assert!( 117 BitmapFrameAllocator::is_used(frame_idx), 118 "backing frame {} must be marked used", 119 i 120 ); 121 }); 122 } 123 124 ptable.destroy(pid, &mut allocator); 125 } 126); 127 128crate::kernel_test!( 129 fn vregion_map_and_access() { 130 let mut allocator = BitmapFrameAllocator; 131 let mut ptable = PROCESSES.lock(); 132 let created = ptable.allocate(&mut allocator).expect("alloc"); 133 ptable.start(created).expect("start"); 134 let pid = created.pid(); 135 helpers::bootstrap_test_cnode(pid, &mut ptable); 136 137 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false); 138 let (cnode_id, cnode_gen, depth, gv, gb) = 139 cnode::cnode_coords(pid, &ptable).expect("coords"); 140 let dest_slot = 60u64; 141 let page_count = 4u16; 142 let vaddr_base = 0x20_0000u64; 143 144 { 145 let mut pool = POOL.lock_after(&ptable); 146 kernel_retype( 147 &mut pool, 148 None, 149 ut_id, 150 ut_gen, 151 ObjectTag::VRegion, 152 0, 153 cnode_id, 154 cnode_gen, 155 dest_slot, 156 depth, 157 gv, 158 gb, 159 page_count as u32, 160 ) 161 .expect("retype vregion"); 162 } 163 164 let (vr_phys, vr_gen, backing_phys) = { 165 let pool = POOL.lock_after(&ptable); 166 let cap = 167 cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_slot, depth, gv, gb) 168 .expect("read slot"); 169 let vr = pool 170 .read_as::<VRegionObject>(cap.phys(), cap.generation()) 171 .expect("read vregion"); 172 (cap.phys(), cap.generation(), vr.phys_base) 173 }; 174 175 let pml4_phys = ptable.exec(pid).map(|e| e.pml4_phys).expect("pml4"); 176 let mut frame_alloc = BitmapFrameAllocator; 177 178 (0..page_count as u64).for_each(|i| { 179 let page_phys = PhysAddr::new(backing_phys + i * 4096); 180 crate::mem::addr::zero_frame(page_phys); 181 let phys_frame = PhysFrame::containing_address(page_phys); 182 let page_vaddr = x86_64::VirtAddr::new(vaddr_base + i * 4096); 183 address_space::map_user_page_inner( 184 pml4_phys, 185 page_vaddr, 186 phys_frame, 187 PageAccess::ReadWrite, 188 &mut frame_alloc, 189 ) 190 .unwrap_or_else(|e| panic!("map page {} failed: {:?}", i, e)); 191 }); 192 193 { 194 let mut pool = POOL.lock_after(&ptable); 195 let vr = pool 196 .write_as::<VRegionObject>(vr_phys, vr_gen) 197 .expect("write vregion"); 198 vr.owner_pid = pid.raw(); 199 vr.owner_vaddr = vaddr_base; 200 vr.flags = lancer_core::types::VRegionFlags::try_new(lancer_core::types::VRegionFlags::WRITABLE).unwrap(); 201 } 202 203 (0..page_count as u64).for_each(|i| { 204 let resolved = crate::syscall::resolve_user_page( 205 pml4_phys.raw(), 206 vaddr_base + i * 4096, 207 true, 208 false, 209 ); 210 assert!( 211 resolved.is_some(), 212 "page {} must be resolvable in PML4", 213 i 214 ); 215 let resolved_phys = resolved.unwrap(); 216 assert!( 217 resolved_phys == backing_phys + i * 4096, 218 "page {} resolved phys {:#x} != expected {:#x}", 219 i, 220 resolved_phys, 221 backing_phys + i * 4096, 222 ); 223 }); 224 225 (0..page_count as u64).for_each(|i| { 226 let page_phys = PhysAddr::new(backing_phys + i * 4096); 227 let page_virt = crate::mem::addr::phys_to_virt(page_phys); 228 let ptr = page_virt.as_mut_ptr::<u64>(); 229 unsafe { 230 core::ptr::write_volatile(ptr, 0xDEAD_BEEF_0000 + i); 231 let val = core::ptr::read_volatile(ptr); 232 assert!( 233 val == 0xDEAD_BEEF_0000 + i, 234 "page {} readback mismatch: got {:#x}", 235 i, 236 val 237 ); 238 } 239 }); 240 241 ptable.destroy(pid, &mut allocator); 242 } 243); 244 245crate::kernel_test!( 246 fn vregion_backing_pages_zeroed() { 247 let mut allocator = BitmapFrameAllocator; 248 let mut ptable = PROCESSES.lock(); 249 let created = ptable.allocate(&mut allocator).expect("alloc"); 250 ptable.start(created).expect("start"); 251 let pid = created.pid(); 252 helpers::bootstrap_test_cnode(pid, &mut ptable); 253 254 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false); 255 let (cnode_id, cnode_gen, depth, gv, gb) = 256 cnode::cnode_coords(pid, &ptable).expect("coords"); 257 258 { 259 let mut pool = POOL.lock_after(&ptable); 260 kernel_retype( 261 &mut pool, 262 None, 263 ut_id, 264 ut_gen, 265 ObjectTag::VRegion, 266 0, 267 cnode_id, 268 cnode_gen, 269 70, 270 depth, 271 gv, 272 gb, 273 4, 274 ) 275 .expect("retype vregion"); 276 } 277 278 let backing_phys = { 279 let pool = POOL.lock_after(&ptable); 280 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 70, depth, gv, gb) 281 .expect("read slot"); 282 pool.read_as::<VRegionObject>(cap.phys(), cap.generation()) 283 .expect("read vregion") 284 .phys_base 285 }; 286 287 (0..4u64).for_each(|i| { 288 let page_phys = PhysAddr::new(backing_phys + i * 4096); 289 crate::mem::addr::zero_frame(page_phys); 290 291 let page_virt = crate::mem::addr::phys_to_virt(page_phys); 292 let slice = 293 unsafe { core::slice::from_raw_parts(page_virt.as_ptr::<u8>(), 4096) }; 294 assert!( 295 slice.iter().all(|&b| b == 0), 296 "backing page {} not zeroed after zero_frame", 297 i 298 ); 299 }); 300 301 ptable.destroy(pid, &mut allocator); 302 } 303); 304 305crate::kernel_test!( 306 fn vregion_destroy_unmaps_owner() { 307 let mut allocator = BitmapFrameAllocator; 308 let mut ptable = PROCESSES.lock(); 309 let created = ptable.allocate(&mut allocator).expect("alloc"); 310 ptable.start(created).expect("start"); 311 let pid = created.pid(); 312 helpers::bootstrap_test_cnode(pid, &mut ptable); 313 314 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false); 315 let (cnode_id, cnode_gen, depth, gv, gb) = 316 cnode::cnode_coords(pid, &ptable).expect("coords"); 317 let dest_slot = 80u64; 318 let page_count = 2u16; 319 let vaddr_base = 0x30_0000u64; 320 321 { 322 let mut pool = POOL.lock_after(&ptable); 323 kernel_retype( 324 &mut pool, 325 None, 326 ut_id, 327 ut_gen, 328 ObjectTag::VRegion, 329 0, 330 cnode_id, 331 cnode_gen, 332 dest_slot, 333 depth, 334 gv, 335 gb, 336 page_count as u32, 337 ) 338 .expect("retype vregion"); 339 } 340 341 let (vr_obj_phys, vr_gen, backing_phys) = { 342 let pool = POOL.lock_after(&ptable); 343 let cap = 344 cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_slot, depth, gv, gb) 345 .expect("read slot"); 346 let vr = pool 347 .read_as::<VRegionObject>(cap.phys(), cap.generation()) 348 .expect("read vregion"); 349 (cap.phys(), cap.generation(), vr.phys_base) 350 }; 351 352 let pml4_phys = ptable.exec(pid).map(|e| e.pml4_phys).expect("pml4"); 353 let mut frame_alloc = BitmapFrameAllocator; 354 355 (0..page_count as u64).for_each(|i| { 356 let page_phys = PhysAddr::new(backing_phys + i * 4096); 357 crate::mem::addr::zero_frame(page_phys); 358 let phys_frame = PhysFrame::containing_address(page_phys); 359 let page_vaddr = x86_64::VirtAddr::new(vaddr_base + i * 4096); 360 address_space::map_user_page_inner( 361 pml4_phys, 362 page_vaddr, 363 phys_frame, 364 PageAccess::ReadWrite, 365 &mut frame_alloc, 366 ) 367 .expect("map page"); 368 }); 369 370 { 371 let mut pool = POOL.lock_after(&ptable); 372 let vr = pool 373 .write_as::<VRegionObject>(vr_obj_phys, vr_gen) 374 .expect("write vregion"); 375 vr.owner_pid = pid.raw(); 376 vr.owner_vaddr = vaddr_base; 377 vr.flags = lancer_core::types::VRegionFlags::try_new(lancer_core::types::VRegionFlags::WRITABLE).unwrap(); 378 } 379 380 (0..page_count as u64).for_each(|i| { 381 assert!( 382 crate::syscall::resolve_user_page( 383 pml4_phys.raw(), 384 vaddr_base + i * 4096, 385 false, 386 false, 387 ) 388 .is_some(), 389 "page {} must be mapped before destroy", 390 i 391 ); 392 }); 393 394 { 395 let (_new_gen, freed) = POOL 396 .lock_after(&ptable) 397 .revoke_phys(vr_obj_phys, vr_gen) 398 .expect("revoke"); 399 freed.inspect(|(phys, tag)| { 400 crate::cap::ops::cleanup_by_tag_with_ptable(*tag, *phys, &mut ptable); 401 }); 402 } 403 404 (0..page_count as u64).for_each(|i| { 405 assert!( 406 crate::syscall::resolve_user_page( 407 pml4_phys.raw(), 408 vaddr_base + i * 4096, 409 false, 410 false, 411 ) 412 .is_none(), 413 "page {} must be unmapped after destroy", 414 i 415 ); 416 }); 417 418 ptable.destroy(pid, &mut allocator); 419 } 420); 421 422crate::kernel_test!( 423 fn vregion_device_untyped_rejected() { 424 let mut allocator = BitmapFrameAllocator; 425 let mut ptable = PROCESSES.lock(); 426 let created = ptable.allocate(&mut allocator).expect("alloc"); 427 ptable.start(created).expect("start"); 428 let pid = created.pid(); 429 helpers::bootstrap_test_cnode(pid, &mut ptable); 430 431 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, true); 432 let (cnode_id, cnode_gen, depth, gv, gb) = 433 cnode::cnode_coords(pid, &ptable).expect("coords"); 434 435 let result = { 436 let mut pool = POOL.lock_after(&ptable); 437 kernel_retype( 438 &mut pool, 439 None, 440 ut_id, 441 ut_gen, 442 ObjectTag::VRegion, 443 0, 444 cnode_id, 445 cnode_gen, 446 90, 447 depth, 448 gv, 449 gb, 450 4, 451 ) 452 }; 453 454 assert!( 455 result.is_err(), 456 "device untyped must reject VRegion retype" 457 ); 458 459 ptable.destroy(pid, &mut allocator); 460 } 461); 462 463crate::kernel_test!( 464 fn vregion_zero_page_count_noop() { 465 let mut allocator = BitmapFrameAllocator; 466 let mut ptable = PROCESSES.lock(); 467 let created = ptable.allocate(&mut allocator).expect("alloc"); 468 ptable.start(created).expect("start"); 469 let pid = created.pid(); 470 helpers::bootstrap_test_cnode(pid, &mut ptable); 471 472 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false); 473 let (cnode_id, cnode_gen, depth, gv, gb) = 474 cnode::cnode_coords(pid, &ptable).expect("coords"); 475 476 let result = { 477 let mut pool = POOL.lock_after(&ptable); 478 kernel_retype( 479 &mut pool, 480 None, 481 ut_id, 482 ut_gen, 483 ObjectTag::VRegion, 484 0, 485 cnode_id, 486 cnode_gen, 487 91, 488 depth, 489 gv, 490 gb, 491 0, 492 ) 493 }; 494 495 assert!( 496 result.is_ok(), 497 "page_count=0 must return Ok(()) (no-op)" 498 ); 499 500 ptable.destroy(pid, &mut allocator); 501 } 502); 503 504crate::kernel_test!( 505 fn vregion_contiguous_backing() { 506 let mut allocator = BitmapFrameAllocator; 507 let mut ptable = PROCESSES.lock(); 508 let created = ptable.allocate(&mut allocator).expect("alloc"); 509 ptable.start(created).expect("start"); 510 let pid = created.pid(); 511 helpers::bootstrap_test_cnode(pid, &mut ptable); 512 513 let (ut_id, ut_gen, _phys) = helpers::allocate_untyped(&ptable, false); 514 let (cnode_id, cnode_gen, depth, gv, gb) = 515 cnode::cnode_coords(pid, &ptable).expect("coords"); 516 let page_count = 8u16; 517 518 { 519 let mut pool = POOL.lock_after(&ptable); 520 kernel_retype( 521 &mut pool, 522 None, 523 ut_id, 524 ut_gen, 525 ObjectTag::VRegion, 526 0, 527 cnode_id, 528 cnode_gen, 529 95, 530 depth, 531 gv, 532 gb, 533 page_count as u32, 534 ) 535 .expect("retype vregion"); 536 } 537 538 let backing_phys = { 539 let pool = POOL.lock_after(&ptable); 540 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, 95, depth, gv, gb) 541 .expect("read slot"); 542 pool.read_as::<VRegionObject>(cap.phys(), cap.generation()) 543 .expect("read vregion") 544 .phys_base 545 }; 546 547 assert!( 548 backing_phys % 4096 == 0, 549 "backing phys {:#x} must be page-aligned", 550 backing_phys 551 ); 552 553 let pml4_phys = ptable.exec(pid).map(|e| e.pml4_phys).expect("pml4"); 554 let vaddr_base = 0x40_0000u64; 555 let mut frame_alloc = BitmapFrameAllocator; 556 557 (0..page_count as u64).for_each(|i| { 558 let page_phys = PhysAddr::new(backing_phys + i * 4096); 559 crate::mem::addr::zero_frame(page_phys); 560 let phys_frame = PhysFrame::containing_address(page_phys); 561 address_space::map_user_page_inner( 562 pml4_phys, 563 x86_64::VirtAddr::new(vaddr_base + i * 4096), 564 phys_frame, 565 PageAccess::ReadWrite, 566 &mut frame_alloc, 567 ) 568 .expect("map page"); 569 }); 570 571 (0..page_count as u64).for_each(|i| { 572 let resolved = crate::syscall::resolve_user_page( 573 pml4_phys.raw(), 574 vaddr_base + i * 4096, 575 false, 576 false, 577 ) 578 .unwrap_or_else(|| panic!("page {} not mapped", i)); 579 assert!( 580 resolved == backing_phys + i * 4096, 581 "page {} should map to contiguous phys: {:#x} vs expected {:#x}", 582 i, 583 resolved, 584 backing_phys + i * 4096, 585 ); 586 }); 587 588 ptable.destroy(pid, &mut allocator); 589 } 590); 591 592crate::kernel_test!( 593 fn vregion_exceeds_max_rejected() { 594 let mut allocator = BitmapFrameAllocator; 595 let mut ptable = PROCESSES.lock(); 596 let created = ptable.allocate(&mut allocator).expect("alloc"); 597 ptable.start(created).expect("start"); 598 let pid = created.pid(); 599 helpers::bootstrap_test_cnode(pid, &mut ptable); 600 601 let (ut_id, ut_gen, _phys) = helpers::allocate_small_untyped(&ptable, 22); 602 let (cnode_id, cnode_gen, depth, gv, gb) = 603 cnode::cnode_coords(pid, &ptable).expect("coords"); 604 605 let result = { 606 let mut pool = POOL.lock_after(&ptable); 607 kernel_retype( 608 &mut pool, 609 None, 610 ut_id, 611 ut_gen, 612 ObjectTag::VRegion, 613 0, 614 cnode_id, 615 cnode_gen, 616 100, 617 depth, 618 gv, 619 gb, 620 513, 621 ) 622 }; 623 assert!(result.is_err(), "page_count=513 exceeds MAX_VREGION_PAGES"); 624 625 ptable.destroy(pid, &mut allocator); 626 } 627);