Nothing to see here, move along
at main 122 lines 3.5 kB view raw
1use crate::mem::addr; 2use crate::mem::phys::BitmapFrameAllocator; 3use crate::sync::IrqMutex; 4use lancer_core::object_layout::KernelObject; 5use x86_64::PhysAddr; 6 7const SLOTS_PER_FRAME: usize = 64; 8const MAX_FRAMES: usize = 256; 9const SLOT_SIZE: usize = 64; 10const INIT_FRAMES: usize = 192; 11 12struct KernelObjectAllocatorInner { 13 frame_phys: [u64; MAX_FRAMES], 14 bitmap: [u64; MAX_FRAMES], 15 frame_count: usize, 16} 17 18impl KernelObjectAllocatorInner { 19 const fn new() -> Self { 20 Self { 21 frame_phys: [0; MAX_FRAMES], 22 bitmap: [0; MAX_FRAMES], 23 frame_count: 0, 24 } 25 } 26 27 fn install_frames(&mut self, phys_addrs: &[u64]) { 28 phys_addrs 29 .iter() 30 .for_each(|&phys| match self.frame_count < MAX_FRAMES { 31 true => { 32 self.frame_phys[self.frame_count] = phys; 33 self.bitmap[self.frame_count] = 0; 34 self.frame_count += 1; 35 } 36 false => {} 37 }); 38 } 39 40 fn alloc_slot(&mut self) -> Option<u64> { 41 (0..self.frame_count).find_map(|fi| { 42 let bm = self.bitmap[fi]; 43 match bm == u64::MAX { 44 true => None, 45 false => { 46 let bit = (!bm).trailing_zeros() as usize; 47 self.bitmap[fi] |= 1u64 << bit; 48 Some(self.frame_phys[fi] + (bit * SLOT_SIZE) as u64) 49 } 50 } 51 }) 52 } 53 54 fn free_slot(&mut self, phys: u64) -> bool { 55 (0..self.frame_count) 56 .find(|&fi| { 57 let base = self.frame_phys[fi]; 58 phys >= base && phys < base + 4096 59 }) 60 .map(|fi| { 61 let offset = (phys - self.frame_phys[fi]) as usize; 62 let bit = offset / SLOT_SIZE; 63 let mask = 1u64 << bit; 64 let was_allocated = self.bitmap[fi] & mask != 0; 65 debug_assert!( 66 was_allocated, 67 "kernel_objects: double-free at phys {phys:#x}" 68 ); 69 self.bitmap[fi] &= !mask; 70 was_allocated 71 }) 72 .unwrap_or(false) 73 } 74} 75 76static KERNEL_OBJ_ALLOC: IrqMutex<KernelObjectAllocatorInner, 3> = 77 IrqMutex::new(KernelObjectAllocatorInner::new()); 78 79pub fn init(allocator: &mut BitmapFrameAllocator) { 80 let mut frame_addrs = [0u64; INIT_FRAMES]; 81 let count = (0..INIT_FRAMES) 82 .scan((), |_, _| allocator.allocate()) 83 .enumerate() 84 .map(|(i, frame)| { 85 let phys = frame.phys_addr(); 86 let virt = addr::phys_to_virt(phys); 87 unsafe { 88 core::ptr::write_bytes(virt.as_mut_ptr::<u8>(), 0, 4096); 89 } 90 frame_addrs[i] = phys.as_u64(); 91 core::mem::forget(frame); 92 i + 1 93 }) 94 .last() 95 .unwrap_or(0); 96 97 { 98 let mut alloc = KERNEL_OBJ_ALLOC.lock(); 99 alloc.install_frames(&frame_addrs[..count]); 100 } 101 102 crate::kprintln!( 103 " KernelObjectAllocator: {} frames ({} slots)", 104 count, 105 count * SLOTS_PER_FRAME, 106 ); 107} 108 109pub fn alloc_slot() -> Option<u64> { 110 KERNEL_OBJ_ALLOC.lock().alloc_slot() 111} 112 113pub fn write_at<T: KernelObject>(phys: u64, obj: T) { 114 let virt = addr::phys_to_virt(PhysAddr::new(phys)); 115 unsafe { 116 core::ptr::write(virt.as_mut_ptr::<T>(), obj); 117 } 118} 119 120pub fn free_slot(phys: u64) { 121 let _ = KERNEL_OBJ_ALLOC.lock().free_slot(phys); 122}