Files
RedBear-OS/src/memory/mod.rs
T

121 lines
2.9 KiB
Rust

//! # 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<Frame> {
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<PartialAllocStrategy>, 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<Frame> {
if self.start <= self.end {
let frame = self.start.clone();
self.start.number += 1;
Some(frame)
} else {
None
}
}
}