Nothing to see here, move along
at main 293 lines 9.7 kB view raw
1use crate::cap::cnode; 2use crate::cap::pool::POOL; 3use crate::cap::retype; 4use crate::mem::phys::BitmapFrameAllocator; 5use crate::proc::address_space; 6use crate::proc::{PROCESSES, ProcessState}; 7use lancer_core::object_tag::ObjectTag; 8 9fn retype_thread( 10 ptable: &mut crate::sync::IrqMutexGuard<'_, crate::proc::ProcessManager, 0>, 11 ut_id: crate::types::ObjPhys, 12 ut_gen: crate::types::Generation, 13 parent_pid: crate::types::Pid, 14 dest_slot: u64, 15) -> Result<crate::types::Pid, crate::error::KernelError> { 16 let (cnode_id, cnode_gen, depth, gv, gb) = cnode::cnode_coords(parent_pid, ptable)?; 17 let mut pool = POOL.lock_after(ptable); 18 retype::retype_thread_from_untyped( 19 &mut pool, ptable, ut_id, ut_gen, parent_pid, cnode_id, cnode_gen, dest_slot, depth, gv, gb, 20 ) 21} 22 23struct ThreadPair { 24 owner_pid: crate::types::Pid, 25 child_pid: crate::types::Pid, 26} 27 28fn with_thread_pair( 29 dest_slot: u64, 30 body: fn(&mut crate::sync::IrqMutexGuard<'_, crate::proc::ProcessManager, 0>, &ThreadPair), 31) { 32 let mut allocator = BitmapFrameAllocator; 33 let mut ptable = PROCESSES.lock(); 34 35 let created = ptable.allocate(&mut allocator).expect("alloc owner"); 36 ptable.start(created).expect("start"); 37 let owner_pid = created.pid(); 38 crate::tests::helpers::bootstrap_test_cnode(owner_pid, &mut ptable); 39 40 let (ut_id, ut_gen, _) = crate::tests::helpers::allocate_small_untyped(&ptable, 16); 41 let child_pid = 42 retype_thread(&mut ptable, ut_id, ut_gen, owner_pid, dest_slot).expect("retype thread"); 43 44 let pair = ThreadPair { 45 owner_pid, 46 child_pid, 47 }; 48 body(&mut ptable, &pair); 49 50 ptable.destroy(child_pid, &mut allocator); 51 ptable.destroy(owner_pid, &mut allocator); 52} 53 54crate::kernel_test!( 55 fn thread_create_shares_pml4() { 56 with_thread_pair(200, |ptable, p| { 57 let parent_pml4 = ptable.exec(p.owner_pid).unwrap().pml4_phys; 58 assert!( 59 ptable.exec(p.child_pid).unwrap().pml4_phys == parent_pml4, 60 "thread must share parent PML4" 61 ); 62 63 let refcount = address_space::pml4_ref_get(parent_pml4.raw()); 64 assert!(refcount == 2, "PML4 refcount must be 2, got {}", refcount); 65 }); 66 } 67); 68 69crate::kernel_test!( 70 fn thread_create_independent_context() { 71 with_thread_pair(201, |ptable, p| { 72 assert!( 73 ptable[p.child_pid].state() == ProcessState::Created, 74 "thread initial state must be Created" 75 ); 76 assert!( 77 p.child_pid != p.owner_pid, 78 "thread must have a different PID" 79 ); 80 }); 81 } 82); 83 84crate::kernel_test!( 85 fn thread_teardown_preserves_address_space() { 86 let mut allocator = BitmapFrameAllocator; 87 let mut ptable = PROCESSES.lock(); 88 89 let created = ptable.allocate(&mut allocator).expect("alloc owner"); 90 ptable.start(created).expect("start"); 91 let owner_pid = created.pid(); 92 crate::tests::helpers::bootstrap_test_cnode(owner_pid, &mut ptable); 93 94 let (ut_id, ut_gen, _) = crate::tests::helpers::allocate_small_untyped(&ptable, 16); 95 let child_pid = 96 retype_thread(&mut ptable, ut_id, ut_gen, owner_pid, 202).expect("retype thread"); 97 let pml4 = ptable.exec(owner_pid).unwrap().pml4_phys; 98 99 assert!( 100 address_space::pml4_ref_get(pml4.raw()) == 2, 101 "refcount should be 2" 102 ); 103 104 ptable.destroy(child_pid, &mut allocator); 105 106 assert!( 107 address_space::pml4_ref_get(pml4.raw()) == 1, 108 "refcount should drop to 1 after thread destroy" 109 ); 110 assert!(ptable.get(owner_pid).is_some(), "parent must still exist"); 111 assert!( 112 ptable.exec(owner_pid).unwrap().pml4_phys == pml4, 113 "parent PML4 must be unchanged" 114 ); 115 116 ptable.destroy(owner_pid, &mut allocator); 117 } 118); 119 120crate::kernel_test!( 121 fn last_thread_teardown_frees_pml4() { 122 let mut allocator = BitmapFrameAllocator; 123 let mut ptable = PROCESSES.lock(); 124 125 let created = ptable.allocate(&mut allocator).expect("alloc owner"); 126 ptable.start(created).expect("start"); 127 let owner_pid = created.pid(); 128 crate::tests::helpers::bootstrap_test_cnode(owner_pid, &mut ptable); 129 130 let (ut_id, ut_gen, _) = crate::tests::helpers::allocate_small_untyped(&ptable, 16); 131 let child_pid = 132 retype_thread(&mut ptable, ut_id, ut_gen, owner_pid, 203).expect("retype thread"); 133 let pml4 = ptable.exec(owner_pid).unwrap().pml4_phys; 134 135 ptable.destroy(owner_pid, &mut allocator); 136 assert!( 137 address_space::pml4_ref_get(pml4.raw()) == 1, 138 "refcount should be 1 after parent destroy" 139 ); 140 141 ptable.destroy(child_pid, &mut allocator); 142 assert!( 143 address_space::pml4_ref_get(pml4.raw()) == 0, 144 "refcount should be 0 after last thread destroy" 145 ); 146 } 147); 148 149crate::kernel_test!( 150 fn fs_base_default_zero() { 151 with_thread_pair(204, |ptable, p| { 152 assert!( 153 ptable.exec(p.child_pid).unwrap().fs_base == 0, 154 "thread fs_base must default to 0" 155 ); 156 assert!( 157 ptable.exec(p.owner_pid).unwrap().fs_base == 0, 158 "parent fs_base must default to 0" 159 ); 160 }); 161 } 162); 163 164crate::kernel_test!( 165 fn fs_base_stored_per_process() { 166 with_thread_pair(205, |ptable, p| { 167 ptable.exec_mut(p.owner_pid).unwrap().fs_base = 0x7FFF_0000_1000; 168 ptable.exec_mut(p.child_pid).unwrap().fs_base = 0x7FFF_0000_2000; 169 170 assert!( 171 ptable.exec(p.owner_pid).unwrap().fs_base == 0x7FFF_0000_1000, 172 "parent fs_base mismatch" 173 ); 174 assert!( 175 ptable.exec(p.child_pid).unwrap().fs_base == 0x7FFF_0000_2000, 176 "child fs_base mismatch" 177 ); 178 }); 179 } 180); 181 182crate::kernel_test!( 183 fn thread_inherits_parent_cnode() { 184 with_thread_pair(206, |ptable, p| { 185 assert!( 186 ptable.exec(p.child_pid).unwrap().root_cnode() 187 == ptable.exec(p.owner_pid).unwrap().root_cnode(), 188 "thread must inherit parent's root cnode" 189 ); 190 }); 191 } 192); 193 194crate::kernel_test!( 195 fn thread_retype_from_untyped_marks_from_untyped() { 196 with_thread_pair(207, |ptable, p| { 197 assert!( 198 ptable.exec(p.child_pid).unwrap().from_untyped, 199 "thread created via retype must have from_untyped = true" 200 ); 201 }); 202 } 203); 204 205crate::kernel_test!( 206 fn thread_retype_device_untyped_rejected() { 207 let mut allocator = BitmapFrameAllocator; 208 let mut ptable = PROCESSES.lock(); 209 210 let created = ptable.allocate(&mut allocator).expect("alloc owner"); 211 ptable.start(created).expect("start"); 212 let owner_pid = created.pid(); 213 crate::tests::helpers::bootstrap_test_cnode(owner_pid, &mut ptable); 214 215 let (dev_id, dev_gen, _) = crate::tests::helpers::allocate_untyped_inner(&ptable, 16, true); 216 let result = retype_thread(&mut ptable, dev_id, dev_gen, owner_pid, 208); 217 218 assert!( 219 result.is_err(), 220 "thread retype from device untyped must fail" 221 ); 222 223 ptable.destroy(owner_pid, &mut allocator); 224 } 225); 226 227crate::kernel_test!( 228 fn fs_base_msr_round_trip() { 229 let original = crate::sched::switch::read_fs_base(); 230 231 crate::sched::switch::write_fs_base(0x7FFF_DEAD_BEEF); 232 let readback = crate::sched::switch::read_fs_base(); 233 assert!( 234 readback == 0x7FFF_DEAD_BEEF, 235 "fs_base readback mismatch: expected 0x7FFF_DEAD_BEEF, got {:#x}", 236 readback 237 ); 238 239 crate::sched::switch::write_fs_base(0x0000_CAFE_0000); 240 let readback2 = crate::sched::switch::read_fs_base(); 241 assert!( 242 readback2 == 0x0000_CAFE_0000, 243 "fs_base second readback mismatch: expected 0x0000_CAFE_0000, got {:#x}", 244 readback2 245 ); 246 247 crate::sched::switch::write_fs_base(original); 248 } 249); 250 251crate::kernel_test!( 252 fn thread_retype_insufficient_space_rejected() { 253 let mut allocator = BitmapFrameAllocator; 254 let mut ptable = PROCESSES.lock(); 255 256 let created = ptable.allocate(&mut allocator).expect("alloc owner"); 257 ptable.start(created).expect("start"); 258 let owner_pid = created.pid(); 259 crate::tests::helpers::bootstrap_test_cnode(owner_pid, &mut ptable); 260 261 let (ut_id, ut_gen, _) = crate::tests::helpers::allocate_small_untyped(&ptable, 12); 262 263 let (cnode_id, cnode_gen, depth, gv, gb) = 264 cnode::cnode_coords(owner_pid, &ptable).expect("coords"); 265 { 266 let mut pool = POOL.lock_after(&ptable); 267 crate::cap::retype::kernel_retype( 268 &mut pool, 269 Some(&mut *ptable), 270 ut_id, 271 ut_gen, 272 ObjectTag::Endpoint, 273 0, 274 cnode_id, 275 cnode_gen, 276 250, 277 depth, 278 gv, 279 gb, 280 1, 281 ) 282 .expect("consume untyped space"); 283 } 284 285 let result = retype_thread(&mut ptable, ut_id, ut_gen, owner_pid, 209); 286 assert!( 287 result.is_err(), 288 "thread retype from too-small untyped must fail" 289 ); 290 291 ptable.destroy(owner_pid, &mut allocator); 292 } 293);