allocator.rs
use linked_list_allocator::LockedHeap;
use x86_64::structures::paging::mapper::MapToError;
use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB};
use x86_64::VirtAddr;
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
// TODO: choose a better start address
pub const HEAP_START: usize = 0x_2222_0000_0000;
pub const HEAP_SIZE: usize = 512 * 1024; // 500 KiB
/// Initialize the kernel heap
pub fn init_heap(
mapper: &mut impl Mapper<Size4KiB>,
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
) -> Result<(), MapToError<Size4KiB>> {
let heap_start = VirtAddr::new(HEAP_START as u64);
let heap_end = heap_start + HEAP_SIZE - 1u64;
// Get the pages between start & end adresses (inclusive)
let page_range = {
// TODO: larger page sizes
let start_page: Page<Size4KiB> = Page::containing_address(heap_start);
let end_page = Page::containing_address(heap_end);
Page::range_inclusive(start_page, end_page)
};
// Map pages to be usable later
for page in page_range {
let frame = frame_allocator
.allocate_frame()
.ok_or(MapToError::FrameAllocationFailed)?;
let page_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
unsafe { mapper.map_to(page, frame, page_flags, frame_allocator) }?.flush();
}
// Initialize the allocator
unsafe {
ALLOCATOR.lock().init(heap_start.as_mut_ptr(), HEAP_SIZE);
}
Ok(())
}