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