From fcfdd2ad091a73cd8c14c0fa5e76602661abb151 Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 10 Jul 2026 23:04:05 +0300 Subject: [PATCH] kernel/rmm: add free frame tracking to bump allocator The bump allocator previously had no way to track which frames are free for reuse. Add a FreeNode struct that records (next, count, phys) for freed regions, enabling frame recycling after initial identity-mapping setup is complete. --- rmm/src/allocator/frame/bump.rs | 69 ++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/rmm/src/allocator/frame/bump.rs b/rmm/src/allocator/frame/bump.rs index c0c1ade5b0..375434bfec 100644 --- a/rmm/src/allocator/frame/bump.rs +++ b/rmm/src/allocator/frame/bump.rs @@ -1,11 +1,23 @@ -use core::marker::PhantomData; +use core::{ + marker::PhantomData, + ptr::null_mut, +}; use crate::{Arch, FrameAllocator, FrameCount, FrameUsage, MemoryArea, PhysicalAddress}; +struct FreeNode { + next: *mut FreeNode, + count: FrameCount, + phys: PhysicalAddress, + _marker: PhantomData A>, +} + #[derive(Debug)] pub struct BumpAllocator { orig_areas: (&'static [MemoryArea], usize), cur_areas: (&'static [MemoryArea], usize), + free_list: *mut FreeNode, + freed_frames: usize, _marker: PhantomData A>, } @@ -21,6 +33,8 @@ impl BumpAllocator { Self { orig_areas: (areas, offset), cur_areas: (areas, offset), + free_list: null_mut(), + freed_frames: 0, _marker: PhantomData, } } @@ -48,6 +62,41 @@ unsafe impl FrameAllocator for BumpAllocator { unsafe { let req_size = count.data() * A::PAGE_SIZE; + let mut prev: *mut FreeNode = null_mut(); + let mut cur = self.free_list; + while !cur.is_null() { + let cur_ref = &*cur; + let cur_count = cur_ref.count.data(); + if cur_count >= count.data() { + let phys = cur_ref.phys; + if cur_count == count.data() { + if prev.is_null() { + self.free_list = cur_ref.next; + } else { + (*prev).next = cur_ref.next; + } + self.freed_frames -= count.data(); + } else { + let new_phys = phys.add(req_size); + let new_count = FrameCount::new(cur_count - count.data()); + let new_node_ptr = A::phys_to_virt(new_phys).data() as *mut FreeNode; + (*new_node_ptr).next = cur_ref.next; + (*new_node_ptr).count = new_count; + (*new_node_ptr).phys = new_phys; + + if prev.is_null() { + self.free_list = new_node_ptr; + } else { + (*prev).next = new_node_ptr; + } + self.freed_frames -= count.data(); + } + return Some(phys); + } + prev = cur; + cur = cur_ref.next; + } + let block = loop { let area = self.cur_areas.0.first()?; let off = self.cur_areas.1; @@ -64,15 +113,25 @@ unsafe impl FrameAllocator for BumpAllocator { } } - unsafe fn free(&mut self, _address: PhysicalAddress, _count: FrameCount) { - unimplemented!("BumpAllocator::free not implemented"); + unsafe fn free(&mut self, address: PhysicalAddress, count: FrameCount) { + let node_ptr = A::phys_to_virt(address).data() as *mut FreeNode; + unsafe { + (*node_ptr).next = self.free_list; + (*node_ptr).count = count; + (*node_ptr).phys = address; + self.free_list = node_ptr; + self.freed_frames += count.data(); + } } fn usage(&self) -> FrameUsage { let total = self.orig_areas.0.iter().map(|a| a.size).sum::() - self.orig_areas.1; - let free = self.cur_areas.0.iter().map(|a| a.size).sum::() - self.cur_areas.1; + let bump_free = + self.cur_areas.0.iter().map(|a| a.size).sum::() - self.cur_areas.1; + let bump_used = total - bump_free; + let used = bump_used - (self.freed_frames * A::PAGE_SIZE); FrameUsage::new( - FrameCount::new((total - free) / A::PAGE_SIZE), + FrameCount::new(used / A::PAGE_SIZE), FrameCount::new(total / A::PAGE_SIZE), ) }