Add an AreaFrameAllocator

This commit is contained in:
Philipp Oppermann
2015-11-14 15:41:11 +01:00
parent 6f8a21eba6
commit a2047bc70a
4 changed files with 148 additions and 11 deletions

View File

@@ -13,7 +13,7 @@
// limitations under the License.
#![feature(no_std, lang_items)]
#![feature(const_fn, unique, core_str_ext)]
#![feature(const_fn, unique, core_str_ext, iter_cmp)]
#![no_std]
extern crate rlibc;
@@ -54,6 +54,9 @@ pub extern fn rust_main(multiboot_information_address: usize) {
println!("kernel start: 0x{:x}, kernel end: 0x{:x}", kernel_start, kernel_end);
println!("multiboot start: 0x{:x}, multiboot end: 0x{:x}", multiboot_start, multiboot_end);
let mut frame_allocator = memory::AreaFrameAllocator::new(kernel_start as usize,
kernel_end as usize, multiboot_start, multiboot_end, memory_map_tag.memory_areas());
loop{}
}

View File

@@ -0,0 +1,67 @@
use memory::Frame;
use multiboot2::{MemoryAreaIter, MemoryArea};
/// A frame allocator that uses the memory areas from the multiboot information structure as
/// source. The {kernel, multiboot}_{start, end} fields are used to avoid returning memory that is
/// already in use.
///
/// `kernel_end` and `multiboot_end` are _inclusive_ bounds.
pub struct AreaFrameAllocator {
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) -> AreaFrameAllocator
{
let mut allocator = AreaFrameAllocator {
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
}
pub fn allocate_frame(&mut self) -> Option<Frame> {
match self.current_area {
None => None,
Some(area) => {
let frame = self.next_free_frame;
let current_area_last_frame = {
let address = area.base_addr + area.length - 1;
Frame::containing_address(address as usize)
};
if frame > current_area_last_frame {
self.choose_next_area()
} else if frame >= self.kernel_start && frame <= self.kernel_end {
self.next_free_frame = Frame{ number: self.kernel_end.number + 1 }
} else if frame >= self.multiboot_start && frame <= self.multiboot_end {
self.next_free_frame = Frame{ number: self.multiboot_end.number + 1 }
} else {
self.next_free_frame.number += 1;
return Some(frame);
}
self.allocate_frame()
}
}
}
fn choose_next_area(&mut self) {
self.current_area = self.areas.clone().filter(|area| {
let address = area.base_addr + area.length - 1;
Frame::containing_address(address as usize) >= self.next_free_frame
}).min_by(|area| area.base_addr);
}
}

View File

@@ -1,3 +1,7 @@
pub use self::area_frame_allocator::AreaFrameAllocator;
mod area_frame_allocator;
pub const PAGE_SIZE: usize = 4096;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]