//! # Memory management //! Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/allocating-frames.html) use crate::arch::rmm::FRAME_ALLOCATOR; pub use crate::paging::{PAGE_SIZE, PhysicalAddress}; use rmm::{ FrameAllocator, FrameCount, }; use syscall::{PartialAllocStrategy, PhysallocFlags}; /// 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 } /// Get the number of frames available pub fn free_frames() -> usize { unsafe { FRAME_ALLOCATOR.usage().free().data() } } /// Get the number of frames used pub fn used_frames() -> usize { unsafe { FRAME_ALLOCATOR.usage().used().data() } } /// Allocate a range of frames pub fn allocate_frames(count: usize) -> Option { unsafe { FRAME_ALLOCATOR.allocate(FrameCount::new(count)).map(|phys| { Frame::containing_address(PhysicalAddress::new(phys.data())) }) } } pub fn allocate_frames_complex(count: usize, flags: PhysallocFlags, strategy: Option, min: usize) -> Option<(Frame, usize)> { if count == min && flags == PhysallocFlags::SPACE_64 && strategy.is_none() { return allocate_frames(count).map(|frame| (frame, count)); } println!( "!!!! allocate_frames_complex not implemented for count {}, flags {:?}, strategy {:?}, min {}", count, flags, strategy, min ); return None; } /// Deallocate a range of frames frame pub fn deallocate_frames(frame: Frame, count: usize) { unsafe { FRAME_ALLOCATOR.free( rmm::PhysicalAddress::new(frame.start_address().data()), FrameCount::new(count) ); } } /// 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.data() / PAGE_SIZE } } //TODO: Set private pub fn range_inclusive(start: Frame, end: Frame) -> FrameIter { FrameIter { start, 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 } } }