diff --git a/src/main.rs b/src/main.rs index 6391b9e7a..a248458f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { blog_os::init(); let mut mapper = unsafe { memory::init(boot_info.physical_memory_offset) }; - let mut frame_allocator = memory::init_frame_allocator(&boot_info.memory_map); + let mut frame_allocator = memory::BootInfoFrameAllocator::init(&boot_info.memory_map); // map a previously unmapped page let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000)); diff --git a/src/memory.rs b/src/memory.rs index e05d97402..67f6f76f0 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -23,24 +23,6 @@ pub unsafe fn init(physical_memory_offset: u64) -> impl MapperAllSizes { MappedPageTable::new(level_4_table, phys_to_virt) } -/// Create a FrameAllocator from the passed memory map -pub fn init_frame_allocator( - memory_map: &'static MemoryMap, -) -> BootInfoFrameAllocator> { - // get usable regions from memory map - let regions = memory_map - .iter() - .filter(|r| r.region_type == MemoryRegionType::Usable); - // map each region to its address range - let addr_ranges = regions.map(|r| r.range.start_addr()..r.range.end_addr()); - // transform to an iterator of frame start addresses - let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); - // create `PhysFrame` types from the start addresses - let frames = frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))); - - BootInfoFrameAllocator { frames } -} - /// Returns a mutable reference to the active level 4 table. /// /// This function is unsafe because the caller must guarantee that the @@ -83,18 +65,41 @@ impl FrameAllocator for EmptyFrameAllocator { } } -pub struct BootInfoFrameAllocator -where - I: Iterator, -{ - frames: I, +pub struct BootInfoFrameAllocator { + memory_map: &'static MemoryMap, + last_yielded_frame: PhysFrame, +} + +impl BootInfoFrameAllocator { + /// Create a FrameAllocator from the passed memory map + pub fn init(memory_map: &'static MemoryMap) -> Self { + BootInfoFrameAllocator { + memory_map, + last_yielded_frame: PhysFrame::containing_address(PhysAddr::new(0)), + } + } + + fn usable_frames(&self) -> impl Iterator { + // get usable regions from memory map + let regions = self.memory_map.iter(); + let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); + // map each region to its address range + let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); + // transform to an iterator of frame start addresses + let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); + // create `PhysFrame` types from the start addresses + frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + } } -impl FrameAllocator for BootInfoFrameAllocator -where - I: Iterator, -{ +impl FrameAllocator for BootInfoFrameAllocator { fn allocate_frame(&mut self) -> Option { - self.frames.next() + let usable_frames = self.usable_frames(); + let mut frames = usable_frames.filter(|frame| frame > &self.last_yielded_frame); + let frame = frames.next(); + if let Some(frame) = frame { + self.last_yielded_frame = frame.clone(); + } + frame } }