mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Merge pull request #595 from phil-opp/redesign-frame-allocator
Avoid generic impl trait parameters in BootInfoFrameAllocator
This commit is contained in:
@@ -11,14 +11,14 @@ use core::panic::PanicInfo;
|
|||||||
entry_point!(kernel_main);
|
entry_point!(kernel_main);
|
||||||
|
|
||||||
fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
||||||
use blog_os::memory;
|
use blog_os::memory::{self, BootInfoFrameAllocator};
|
||||||
use x86_64::{structures::paging::Page, VirtAddr};
|
use x86_64::{structures::paging::Page, VirtAddr};
|
||||||
|
|
||||||
println!("Hello World{}", "!");
|
println!("Hello World{}", "!");
|
||||||
blog_os::init();
|
blog_os::init();
|
||||||
|
|
||||||
let mut mapper = unsafe { memory::init(boot_info.physical_memory_offset) };
|
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
|
// map a previously unmapped page
|
||||||
let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));
|
let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));
|
||||||
|
|||||||
@@ -23,24 +23,6 @@ pub unsafe fn init(physical_memory_offset: u64) -> impl MapperAllSizes {
|
|||||||
MappedPageTable::new(level_4_table, phys_to_virt)
|
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.
|
/// Returns a mutable reference to the active level 4 table.
|
||||||
///
|
///
|
||||||
/// This function is unsafe because the caller must guarantee that the
|
/// This function is unsafe because the caller must guarantee that the
|
||||||
@@ -83,18 +65,39 @@ impl FrameAllocator<Size4KiB> for EmptyFrameAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BootInfoFrameAllocator<I>
|
/// A FrameAllocator that returns usable frames from the bootloader's memory map.
|
||||||
where
|
pub struct BootInfoFrameAllocator {
|
||||||
I: Iterator<Item = PhysFrame>,
|
memory_map: &'static MemoryMap,
|
||||||
{
|
next: usize,
|
||||||
frames: I,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> FrameAllocator<Size4KiB> for BootInfoFrameAllocator<I>
|
impl BootInfoFrameAllocator {
|
||||||
where
|
/// Create a FrameAllocator from the passed memory map.
|
||||||
I: Iterator<Item = PhysFrame>,
|
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> {
|
fn allocate_frame(&mut self) -> Option<PhysFrame> {
|
||||||
self.frames.next()
|
let frame = self.usable_frames().nth(self.next);
|
||||||
|
self.next += 1;
|
||||||
|
frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user