Nothing to see here, move along
at main 80 lines 2.2 kB view raw
1use limine::memory_map::Entry; 2use x86_64::PhysAddr; 3 4use super::RawSlice; 5use super::addr; 6use super::phys::BitmapFrameAllocator; 7use crate::sync::IrqMutex; 8 9const PAGE_SIZE: u64 = 4096; 10 11#[derive(Debug, Clone, Copy, PartialEq, Eq)] 12pub enum RefcountError { 13 OutOfRange(PhysAddr), 14 Overflow(PhysAddr), 15 Underflow(PhysAddr), 16} 17 18static REFCOUNTS: IrqMutex<RawSlice<u16>, 4> = IrqMutex::new(RawSlice::empty()); 19 20pub fn init(memory_map: &[&Entry]) { 21 let max_addr = memory_map 22 .iter() 23 .filter(|entry| entry.entry_type == limine::memory_map::EntryType::USABLE) 24 .map(|entry| entry.base + entry.length) 25 .fold(0u64, u64::max); 26 27 let total_frames = (max_addr / PAGE_SIZE) as usize; 28 let bytes_needed = total_frames * 2; 29 let frames_needed = bytes_needed.div_ceil(PAGE_SIZE as usize); 30 31 let allocator = BitmapFrameAllocator; 32 let phys_base = allocator 33 .allocate_contiguous(frames_needed) 34 .expect("[refcount] failed to allocate contiguous frames for refcount table"); 35 36 let virt = addr::phys_to_virt(phys_base); 37 let ptr = virt.as_u64() as *mut u16; 38 39 unsafe { 40 core::ptr::write_bytes(ptr, 0, total_frames); 41 } 42 43 let mut rc = REFCOUNTS.lock(); 44 rc.init(ptr, total_frames); 45} 46 47pub fn increment(phys: PhysAddr) -> Result<(), RefcountError> { 48 let idx = (phys.as_u64() / PAGE_SIZE) as usize; 49 let mut rc = REFCOUNTS.lock(); 50 let slot = rc 51 .as_slice_mut() 52 .get_mut(idx) 53 .ok_or(RefcountError::OutOfRange(phys))?; 54 let new = slot.checked_add(1).ok_or(RefcountError::Overflow(phys))?; 55 *slot = new; 56 Ok(()) 57} 58 59pub fn decrement(phys: PhysAddr) -> Result<u16, RefcountError> { 60 let idx = (phys.as_u64() / PAGE_SIZE) as usize; 61 let mut rc = REFCOUNTS.lock(); 62 let slot = rc 63 .as_slice_mut() 64 .get_mut(idx) 65 .ok_or(RefcountError::OutOfRange(phys))?; 66 let new = slot.checked_sub(1).ok_or(RefcountError::Underflow(phys))?; 67 *slot = new; 68 Ok(new) 69} 70 71#[allow(dead_code)] 72pub fn get(phys: PhysAddr) -> u16 { 73 let idx = (phys.as_u64() / PAGE_SIZE) as usize; 74 let rc = REFCOUNTS.lock(); 75 if idx < rc.len() { 76 rc.as_slice()[idx] 77 } else { 78 0 79 } 80}