From 0f5bf89493ff9018f6be9baa6a5e22cc2678011d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Feb 2018 20:36:29 +0100 Subject: [PATCH] -amend --- kernel-rs/src/memory/area_allocator.rs | 74 ++++++++++++++++++++++++++ kernel-rs/src/memory/mod.rs | 19 +++++++ 2 files changed, 93 insertions(+) create mode 100644 kernel-rs/src/memory/area_allocator.rs create mode 100644 kernel-rs/src/memory/mod.rs diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs new file mode 100644 index 00000000..4ce96334 --- /dev/null +++ b/kernel-rs/src/memory/area_allocator.rs @@ -0,0 +1,74 @@ +use memory::*; +use multiboot2::{MemoryAreaIter, MemoryArea}; + +pub struct AreaAllocator { + next_free_frame: Frame, + current_area: Option<&'static MemoryArea>, + areas: MemoryAreaIter, + kernel_start: Frame, + kernel_end: Frame, + multiboot_start: Frame, + multiboot_end: Frame, +} + +impl AreaFrameAllocator { + pub fn new(kernel_start: usize, kernel_end: usize + multiboot_start: usize, multiboot_end: usize + memory_areas: MemoryAreaIter) -> AreaAllocator { + let mut allocator = AreaAllocator { + next_free_frame: Frame::containing_address(0), + current_area: None, + areas: memory_areas, + kernel_start: Frame::containing_address(kernel_start), + kernel_end: Frame::containing_address(kernel_end), + multiboot_start: Frame::containing_address(multiboot_start), + multiboot_end: Frame::containing_address(multiboot_end), + } + allocator.choose_next_area(); + allocator + } + + fn choose_next_area(&mut self) { + // get next area with free frames + self.current_area = self.areas.clone().filter(|area| { + Frame::containing_address(area.end_address()) >= self.next_free_frame + }).min_by_key(|area| area.start_addr()); + + if let Some(area) = self.current_area { + let start_frame = Frame::containing_address(area.start_addr()); + if self.next_free_frame < start_frame { + self.next_free_frame = start_frame; + } + } + } +} + +impl FrameAllocator for AreaFrameAllocator { + fn allocate_frame(&mut self) -> Option { + if let Some(area) = sef.current_area { + let frame = Frame { number: self.next_free_frame.number }, + let current_area_last_frame = Frame::containing_address(area.end_address()); + if frame > current_area_last_frame { + // all frames are taken in this area + self.choose_next_area(); + } else if frame >= self.kernel_start && frame <= kernel_end { + // frame used by kernel + self.next_free_frame = Frame { + number: self.kernel_end.number + 1; + } + } else if frame >= self.multiboot_start && frame <= multiboot_end { + // frame used by multiboot + self.next_free_frame = Frame { + number: self.multiboot_end.number + 1; + } + } else { + self.next_free_frame_number += 1; + return Some(Frame); + } + } else { None } + } + + fn deallocate_frame(&mut self, frame: Frame) { + unimplemented!(); + } +} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs new file mode 100644 index 00000000..667a07cf --- /dev/null +++ b/kernel-rs/src/memory/mod.rs @@ -0,0 +1,19 @@ +pub const PAGE_SIZE: usize = 4096; + +// pub use self::area_allocator::*; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Frame { + number: usize, +} + +impl Frame { + fn containing_address(address: usize) -> Frame { + Frame{ number: address / PAGE_SIZE } + } +} + +pub trait FrameAllocator { + fn allocate_frame(&mut self) -> Option; + fn deallocate_frame(&mut self, frame: Frame); +}