Merge pull request #595 from phil-opp/redesign-frame-allocator

Avoid generic impl trait parameters in BootInfoFrameAllocator
This commit is contained in:
Philipp Oppermann
2019-04-30 13:24:43 +02:00
committed by GitHub
2 changed files with 34 additions and 31 deletions

View File

@@ -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::init_frame_allocator(&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));

View File

@@ -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<impl Iterator<Item = PhysFrame>> {
// 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,39 @@ impl FrameAllocator<Size4KiB> for EmptyFrameAllocator {
}
}
pub struct BootInfoFrameAllocator<I>
where
I: Iterator<Item = PhysFrame>,
{
frames: I,
/// A FrameAllocator that returns usable frames from the bootloader's memory map.
pub struct BootInfoFrameAllocator {
memory_map: &'static MemoryMap,
next: usize,
}
impl<I> FrameAllocator<Size4KiB> for BootInfoFrameAllocator<I>
where
I: Iterator<Item = PhysFrame>,
{
impl BootInfoFrameAllocator {
/// Create a FrameAllocator from the passed memory map.
pub fn init(memory_map: &'static MemoryMap) -> Self {
BootInfoFrameAllocator {
memory_map,
next: 0,
}
}
/// Returns an iterator over the usable frames specified in the memory map.
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> {
// 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<Size4KiB> for BootInfoFrameAllocator {
fn allocate_frame(&mut self) -> Option<PhysFrame> {
self.frames.next()
let frame = self.usable_frames().nth(self.next);
self.next += 1;
frame
}
}