//! # Memory management //! Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/allocating-frames.html) pub use paging::{PAGE_SIZE, PhysicalAddress}; use self::area_frame_alloc::AreaFrameAllocator; use spin::Mutex; pub mod area_frame_alloc; /// The current memory map. It's size is maxed out to 512 entries, due to it being /// from 0x500 to 0x5000 (800 is the absolute total) static mut MEMORY_MAP: [MemoryArea; 512] = [MemoryArea { base_addr: 0, length: 0, _type: 0, acpi: 0 }; 512]; /// Memory does not exist pub const MEMORY_AREA_NULL: u32 = 0; /// Memory is free to use pub const MEMORY_AREA_FREE: u32 = 1; /// Memory is reserved pub const MEMORY_AREA_RESERVED: u32 = 2; /// Memory is used by ACPI, and can be reclaimed pub const MEMORY_AREA_ACPI: u32 = 3; #[derive(Clone)] pub struct MemoryAreaIter { _type: u32, i: usize } impl MemoryAreaIter { fn new(_type: u32) -> Self { MemoryAreaIter { _type: _type, i: 0 } } } impl Iterator for MemoryAreaIter { type Item = &'static MemoryArea; fn next(&mut self) -> Option { while self.i < unsafe { MEMORY_MAP.len() } { let entry = unsafe { &MEMORY_MAP[self.i] }; self.i += 1; if entry._type == self._type { return Some(entry); } } None } } static ALLOCATOR: Mutex> = Mutex::new(None); /// Init memory module /// Must be called once, and only once, pub unsafe fn init(kernel_start: usize, kernel_end: usize) { // Copy memory map from bootloader location for (i, mut entry) in MEMORY_MAP.iter_mut().enumerate() { *entry = *(0x500 as *const MemoryArea).offset(i as isize); if entry.length > 0 { println!("{:?}", entry); } } *ALLOCATOR.lock() = Some(AreaFrameAllocator::new(kernel_start, kernel_end, MemoryAreaIter::new(MEMORY_AREA_FREE))); } /// Allocate a frame pub fn allocate_frame() -> Option { if let Some(ref mut allocator) = *ALLOCATOR.lock() { allocator.allocate_frame() } else { panic!("frame allocator not initialized"); } } /// Deallocate a frame pub fn deallocate_frame(frame: Frame) { if let Some(ref mut allocator) = *ALLOCATOR.lock() { allocator.deallocate_frame(frame) } else { panic!("frame allocator not initialized"); } } /// A memory map area #[derive(Copy, Clone, Debug, Default)] #[repr(packed)] pub struct MemoryArea { pub base_addr: u64, pub length: u64, pub _type: u32, pub acpi: u32 } /// A frame, allocated by the frame allocator. /// Do not add more derives, or make anything `pub`! #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Frame { number: usize } impl Frame { /// Get the address of this frame pub fn start_address(&self) -> PhysicalAddress { PhysicalAddress::new(self.number * PAGE_SIZE) } //TODO: Set private pub fn clone(&self) -> Frame { Frame { number: self.number } } /// Create a frame containing `address` pub fn containing_address(address: PhysicalAddress) -> Frame { Frame { number: address.get() / PAGE_SIZE } } //TODO: Set private pub fn range_inclusive(start: Frame, end: Frame) -> FrameIter { FrameIter { start: start, end: end, } } } pub struct FrameIter { start: Frame, end: Frame, } impl Iterator for FrameIter { type Item = Frame; fn next(&mut self) -> Option { if self.start <= self.end { let frame = self.start.clone(); self.start.number += 1; Some(frame) } else { None } } } pub trait FrameAllocator { fn allocate_frame(&mut self) -> Option; fn deallocate_frame(&mut self, frame: Frame); }