From 180c77d1f473254aeec630ad9a9b00f4aca93a87 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 30 Apr 2019 10:27:22 +0200 Subject: [PATCH 1/3] Avoid generic impl trait parameters in BootInfoFrameAllocator --- src/main.rs | 2 +- src/memory.rs | 65 ++++++++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6391b9e7..a248458f 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 e05d9740..70cf9025 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,43 @@ impl FrameAllocator for EmptyFrameAllocator { } } -pub struct BootInfoFrameAllocator -where - I: Iterator, -{ - frames: I, +/// A FrameAllocator that returns usable frames from the bootloader's memory map. +pub struct BootInfoFrameAllocator { + memory_map: &'static MemoryMap, + last_yielded_frame: PhysFrame, } -impl FrameAllocator for BootInfoFrameAllocator -where - I: Iterator, -{ - fn allocate_frame(&mut self) -> Option { - self.frames.next() +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)), + } + } + + /// Returns an iterator over the usable frames specified in the memory map. + 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 { + fn allocate_frame(&mut self) -> Option { + 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 } } From 24a9e7abd2e345fdf91e455b8f00e52706cc5ef7 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 30 Apr 2019 12:47:45 +0200 Subject: [PATCH 2/3] Simplify FrameAllocator implementation using Iterator::nth --- src/memory.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/memory.rs b/src/memory.rs index 70cf9025..2e110fce 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -68,7 +68,7 @@ impl FrameAllocator for EmptyFrameAllocator { /// A FrameAllocator that returns usable frames from the bootloader's memory map. pub struct BootInfoFrameAllocator { memory_map: &'static MemoryMap, - last_yielded_frame: PhysFrame, + next: usize, } impl BootInfoFrameAllocator { @@ -76,7 +76,7 @@ impl BootInfoFrameAllocator { pub fn init(memory_map: &'static MemoryMap) -> Self { BootInfoFrameAllocator { memory_map, - last_yielded_frame: PhysFrame::containing_address(PhysAddr::new(0)), + next: 0, } } @@ -96,12 +96,8 @@ impl BootInfoFrameAllocator { impl FrameAllocator for BootInfoFrameAllocator { fn allocate_frame(&mut self) -> Option { - 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(); - } + let frame = self.usable_frames().nth(self.next); + self.next += 1; frame } } From b5ee44621c4df690845cada0c93dd25db658bd11 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 30 Apr 2019 12:59:23 +0200 Subject: [PATCH 3/3] Use an import for initializing BootInfoFrameAllocator --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index a248458f..c31a92b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,14 +11,14 @@ use core::panic::PanicInfo; entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { - use blog_os::memory; + use blog_os::memory::{self, BootInfoFrameAllocator}; use x86_64::{structures::paging::Page, VirtAddr}; println!("Hello World{}", "!"); blog_os::init(); let mut mapper = unsafe { memory::init(boot_info.physical_memory_offset) }; - let mut frame_allocator = memory::BootInfoFrameAllocator::init(&boot_info.memory_map); + let mut frame_allocator = BootInfoFrameAllocator::init(&boot_info.memory_map); // map a previously unmapped page let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));