diff --git a/src/framework/jinux-frame/src/mm/frame_allocator.rs b/src/framework/jinux-frame/src/mm/frame_allocator.rs index b0f81fab7..da43a3963 100644 --- a/src/framework/jinux-frame/src/mm/frame_allocator.rs +++ b/src/framework/jinux-frame/src/mm/frame_allocator.rs @@ -1,78 +1,58 @@ use alloc::vec::Vec; -use spin::Mutex; +use buddy_system_allocator::FrameAllocator; +use limine::{LimineMemmapEntry, LimineMemoryMapEntryType}; +use log::info; +use spin::{Mutex, Once}; use crate::{config::PAGE_SIZE, vm::Paddr}; use super::address::PhysAddr; -use lazy_static::lazy_static; +static FRAME_ALLOCATOR: Once> = Once::new(); -lazy_static! { - static ref FRAME_ALLOCATOR: Mutex = Mutex::new(FreeListAllocator { - current: 0, - end: 0, - free_list: Vec::new(), - }); -} - -trait FrameAllocator { - fn alloc(&mut self) -> Option; - fn dealloc(&mut self, value: usize); -} - -pub struct FreeListAllocator { - current: usize, - end: usize, - free_list: Vec, -} - -impl FreeListAllocator { - fn alloc(&mut self) -> Option { - let mut ret = 0; - if let Some(x) = self.free_list.pop() { - ret = x; - } else if self.current < self.end { - ret = self.current; - self.current += PAGE_SIZE; - }; - Some(ret) - } - - fn dealloc(&mut self, value: usize) { - assert!(!self.free_list.contains(&value)); - self.free_list.push(value); - } -} #[derive(Debug, Clone)] // #[repr(transparent)] pub struct PhysFrame { - start_pa: usize, + frame_index: usize, + need_dealloc: bool, } impl PhysFrame { pub const fn start_pa(&self) -> PhysAddr { - PhysAddr(self.start_pa) + PhysAddr(self.frame_index * PAGE_SIZE) } pub const fn end_pa(&self) -> PhysAddr { - PhysAddr(self.start_pa + PAGE_SIZE) + PhysAddr((self.frame_index + 1) * PAGE_SIZE) } pub fn alloc() -> Option { - FRAME_ALLOCATOR - .lock() - .alloc() - .map(|pa| Self { start_pa: pa }) + FRAME_ALLOCATOR.get().unwrap().lock().alloc(1).map(|pa| Self { + frame_index: pa, + need_dealloc: true, + }) + } + + pub fn alloc_continuous_range(frame_count: usize) -> Option> { + FRAME_ALLOCATOR.get().unwrap().lock().alloc(frame_count).map(|start| { + let mut vector = Vec::new(); + for i in 0..frame_count { + vector.push(Self { + frame_index: start + i, + need_dealloc: true, + }) + } + vector + }) } pub fn alloc_with_paddr(paddr: Paddr) -> Option { // FIXME: need to check whether the physical address is invalid or not - Some(Self { start_pa: paddr }) - } - - pub fn dealloc(pa: usize) { - FRAME_ALLOCATOR.lock().dealloc(pa) + Some(Self { + frame_index: paddr / PAGE_SIZE, + need_dealloc: false, + }) } pub fn alloc_zero() -> Option { @@ -92,11 +72,27 @@ impl PhysFrame { impl Drop for PhysFrame { fn drop(&mut self) { - FRAME_ALLOCATOR.lock().dealloc(self.start_pa); + if self.need_dealloc { + FRAME_ALLOCATOR.get().unwrap().lock().dealloc(self.frame_index, 1); + } } } -pub(crate) fn init(start: usize, size: usize) { - FRAME_ALLOCATOR.lock().current = start; - FRAME_ALLOCATOR.lock().end = start + size; -} +pub(crate) fn init(regions: &Vec<&LimineMemmapEntry>) { + let mut allocator = FrameAllocator::<32>::new(); + for region in regions.iter() { + if region.typ == LimineMemoryMapEntryType::Usable { + assert_eq!(region.base % PAGE_SIZE as u64, 0); + assert_eq!(region.len % PAGE_SIZE as u64, 0); + let start = region.base as usize / PAGE_SIZE; + let end = start + region.len as usize / PAGE_SIZE; + allocator.add_frame(start, end); + info!( + "Found usable region, start:{:x}, end:{:x}", + region.base, + region.base + region.len + ); + } + } + FRAME_ALLOCATOR.call_once(||Mutex::new(allocator)); +} \ No newline at end of file diff --git a/src/framework/jinux-frame/src/mm/mod.rs b/src/framework/jinux-frame/src/mm/mod.rs index c58ccedb8..6174b20f6 100644 --- a/src/framework/jinux-frame/src/mm/mod.rs +++ b/src/framework/jinux-frame/src/mm/mod.rs @@ -56,20 +56,8 @@ pub(crate) fn init() { debug!("Found memory region:{:x?}", **i); memory_regions.push(&**i); } - let mut biggest_region_size = 0; - let mut biggest_region_start = 0; - for i in memory_regions.iter() { - if i.len > biggest_region_size { - biggest_region_size = i.len; - biggest_region_start = i.base; - } - } - if biggest_region_size == 0 { - panic!("Cannot find usable memory region"); - } - // TODO: pass the memory regions to the frame allocator. The frame allocator should use multiple usable area - frame_allocator::init(biggest_region_start as usize, biggest_region_size as usize); + frame_allocator::init(&memory_regions); page_table::init(); MEMORY_REGIONS.call_once(|| memory_regions);