mod buddy;
use buddy::BuddyAllocator;
use core::ops::Range;
use hal::memory::{Frame, FrameAllocator, FrameSize, PAddr, Size4KiB};
use seed::boot_info::BootInfo;
use spinning_top::Spinlock;
pub struct Pmm {
buddy: Spinlock<BuddyAllocator>,
}
impl Pmm {
pub fn new(boot_info: &BootInfo) -> Pmm {
let mut buddy_allocator = BuddyAllocator::new();
for entry in &boot_info.memory_map {
if entry.typ == seed::boot_info::MemoryType::Conventional {
buddy_allocator.free_range(entry.frame_range());
}
}
Pmm { buddy: Spinlock::new(buddy_allocator) }
}
pub fn alloc(&self, count: usize) -> PAddr {
self.buddy.lock().alloc(count).expect("Failed to allocate requested physical memory")
}
pub fn free(&self, base: PAddr, count: usize) {
self.buddy.lock().free(base, count)
}
}
impl<S> FrameAllocator<S> for Pmm
where
S: FrameSize,
{
fn allocate_n(&self, n: usize) -> Range<Frame<S>> {
let start =
self.buddy.lock().alloc(n * S::SIZE / Size4KiB::SIZE).expect("Failed to allocate physical memory!");
Frame::<S>::starts_with(start)..(Frame::<S>::starts_with(start) + n)
}
fn free_n(&self, start: Frame<S>, num_frames: usize) {
self.buddy.lock().free(start.start, num_frames * S::SIZE / Size4KiB::SIZE);
}
}