Nothing to see here, move along
at main 206 lines 6.8 kB view raw
1use lancer_core::bitmap::bitmap_seal::Sealed; 2use lancer_core::bitmap::{BitmapAllocator as BitmapCore, BitmapBacking}; 3use limine::memory_map::{Entry, EntryType}; 4use x86_64::PhysAddr; 5use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB}; 6 7use super::RawSlice; 8use super::addr; 9use super::frame::OwnedFrame; 10use crate::sync::IrqMutex; 11 12const PAGE_SIZE: u64 = 4096; 13 14static BITMAP_PHYS_BASE: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(0); 15static BITMAP_BYTE_COUNT: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(0); 16 17#[allow(dead_code)] 18pub fn bitmap_region() -> (u64, u64) { 19 ( 20 BITMAP_PHYS_BASE.load(core::sync::atomic::Ordering::Relaxed), 21 BITMAP_BYTE_COUNT.load(core::sync::atomic::Ordering::Relaxed), 22 ) 23} 24 25impl Sealed for RawSlice<u64> {} 26impl BitmapBacking for RawSlice<u64> { 27 fn chunks(&self) -> &[u64] { 28 self.as_slice() 29 } 30 31 fn chunks_mut(&mut self) -> &mut [u64] { 32 self.as_slice_mut() 33 } 34} 35 36static BITMAP: IrqMutex<BitmapCore<RawSlice<u64>>, 3> = 37 IrqMutex::new(BitmapCore::from_backing(RawSlice::empty())); 38 39pub struct BitmapFrameAllocator; 40 41impl BitmapFrameAllocator { 42 pub fn init(memory_map: &[&Entry]) { 43 let max_addr = memory_map 44 .iter() 45 .filter(|entry| entry.entry_type == EntryType::USABLE) 46 .map(|entry| entry.base + entry.length) 47 .fold(0u64, u64::max); 48 49 let total_frames = (max_addr / PAGE_SIZE) as usize; 50 let chunks_needed = total_frames.div_ceil(64); 51 let bitmap_bytes = chunks_needed * 8; 52 let bitmap_frames = bitmap_bytes.div_ceil(PAGE_SIZE as usize); 53 54 let bitmap_region = memory_map 55 .iter() 56 .filter(|entry| entry.entry_type == EntryType::USABLE) 57 .find(|entry| entry.length >= (bitmap_frames as u64) * PAGE_SIZE) 58 .expect("[phys] no usable region large enough for bitmap"); 59 60 let bitmap_phys_base = bitmap_region.base; 61 BITMAP_PHYS_BASE.store(bitmap_phys_base, core::sync::atomic::Ordering::Relaxed); 62 BITMAP_BYTE_COUNT.store( 63 (bitmap_frames as u64) * PAGE_SIZE, 64 core::sync::atomic::Ordering::Relaxed, 65 ); 66 let bitmap_virt = addr::phys_to_virt(PhysAddr::new(bitmap_phys_base)); 67 assert!( 68 bitmap_virt.is_aligned(8u64), 69 "bitmap backing memory not 8-byte aligned" 70 ); 71 let bitmap_ptr = bitmap_virt.as_u64() as *mut u64; 72 73 let mut bm = BITMAP.lock(); 74 let mut backing = RawSlice::empty(); 75 backing.init(bitmap_ptr, chunks_needed); 76 *bm = BitmapCore::from_backing(backing); 77 bm.init(total_frames); 78 79 memory_map 80 .iter() 81 .filter(|entry| entry.entry_type == EntryType::USABLE) 82 .for_each(|entry| { 83 let start_frame = (entry.base / PAGE_SIZE) as usize; 84 let end_frame = ((entry.base + entry.length) / PAGE_SIZE) as usize; 85 bm.mark_range_free(start_frame..end_frame); 86 }); 87 88 let bitmap_start_frame = (bitmap_phys_base / PAGE_SIZE) as usize; 89 (bitmap_start_frame..bitmap_start_frame + bitmap_frames).for_each(|idx| bm.mark_used(idx)); 90 91 bm.mark_used(0); 92 } 93 94 pub fn allocate_contiguous(&self, count: usize) -> Option<PhysAddr> { 95 BITMAP 96 .lock() 97 .allocate_contiguous(count) 98 .map(|idx| PhysAddr::new((idx as u64) * PAGE_SIZE)) 99 } 100 101 pub fn allocate(&self) -> Option<OwnedFrame> { 102 let mut bm = BITMAP.lock(); 103 bm.allocate().map(|idx| { 104 let phys = PhysAddr::new((idx as u64) * PAGE_SIZE); 105 OwnedFrame::new(PhysFrame::containing_address(phys)) 106 }) 107 } 108 109 pub(crate) fn free_frame_by_addr(phys: PhysAddr) { 110 let mut bm = BITMAP.lock(); 111 let frame_idx = (phys.as_u64() / PAGE_SIZE) as usize; 112 bm.deallocate(frame_idx).unwrap_or_else(|_| { 113 panic!( 114 "[phys] invariant violation: double-free of frame {:#x}", 115 phys.as_u64() 116 ) 117 }); 118 } 119 120 #[allow(dead_code)] 121 pub fn deallocate(&self, frame: OwnedFrame) { 122 Self::free_frame_by_addr(frame.inner().start_address()); 123 } 124 125 pub fn deallocate_frame(&self, frame: PhysFrame<Size4KiB>) { 126 Self::free_frame_by_addr(frame.start_address()); 127 } 128 129 #[allow(dead_code)] 130 pub fn mark_used(idx: usize) { 131 BITMAP.lock().mark_used(idx); 132 } 133 134 #[allow(dead_code)] 135 pub fn is_used(idx: usize) -> bool { 136 BITMAP.lock().is_used(idx) 137 } 138 139 pub fn total_frames() -> usize { 140 BITMAP.lock().total_items() 141 } 142 143 #[allow(dead_code)] 144 pub fn used_frames() -> usize { 145 BITMAP.lock().used_items() 146 } 147 148 pub fn free_frames() -> usize { 149 BITMAP.lock().free_items() 150 } 151 152 pub fn for_each_used_range<F: FnMut(usize, usize)>(f: &mut F) { 153 BITMAP.lock().for_each_used_range(f); 154 } 155} 156 157unsafe impl FrameAllocator<Size4KiB> for BitmapFrameAllocator { 158 fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> { 159 self.allocate().map(|tf| tf.inner()) 160 } 161} 162 163#[allow(dead_code)] 164pub fn log_memory_map(memory_map: &[&Entry]) { 165 crate::kprintln!(" Memory map ({} entries):", memory_map.len()); 166 memory_map.iter().for_each(|entry| { 167 let entry_type_str = match entry.entry_type { 168 EntryType::USABLE => "Usable", 169 EntryType::RESERVED => "Reserved", 170 EntryType::ACPI_RECLAIMABLE => "ACPI Reclaimable", 171 EntryType::ACPI_NVS => "ACPI NVS", 172 EntryType::BAD_MEMORY => "Bad Memory", 173 EntryType::BOOTLOADER_RECLAIMABLE => "Bootloader Reclaimable", 174 EntryType::EXECUTABLE_AND_MODULES => "Kernel/Modules", 175 EntryType::FRAMEBUFFER => "Framebuffer", 176 _ => "Unknown", 177 }; 178 let size_kb = entry.length / 1024; 179 crate::kprintln!( 180 " {:#016x} - {:#016x} ({:>8} KB) {}", 181 entry.base, 182 entry.base + entry.length, 183 size_kb, 184 entry_type_str 185 ); 186 }); 187} 188 189pub fn frame_stats() -> (usize, usize) { 190 ( 191 BitmapFrameAllocator::total_frames(), 192 BitmapFrameAllocator::free_frames(), 193 ) 194} 195 196#[allow(dead_code)] 197pub fn log_frame_stats() { 198 crate::kprintln!(" Frame allocator stats:"); 199 crate::kprintln!(" Total frames: {}", BitmapFrameAllocator::total_frames()); 200 crate::kprintln!(" Used frames: {}", BitmapFrameAllocator::used_frames()); 201 crate::kprintln!(" Free frames: {}", BitmapFrameAllocator::free_frames()); 202 crate::kprintln!( 203 " Free memory: {} MB", 204 BitmapFrameAllocator::free_frames() * 4096 / (1024 * 1024) 205 ); 206}