Skip to main content

kernel/mem/
heap.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! Kernel heap allocator: a fixed-size [`linked_list_allocator::LockedHeap`] set as
3//! the `#[global_allocator]`. Does not grow after [`init`].
4//!
5//! Authors: MarioS271
6
7use crate::mem::pmm::{Pmm, FRAME_SIZE};
8use crate::mem::vmm::Vmm;
9use crate::panic::kernel_panic;
10use crate::types::panic_codes::PanicCode;
11use x86_64::VirtAddr;
12use x86_64::structures::paging::PageTableFlags;
13use linked_list_allocator::LockedHeap;
14
15/// First virtual address of the heap region (higher-half kernel space).
16static HEAP_BASE_ADDRESS: VirtAddr = VirtAddr::new(0xffff_8080_0000_0000);
17
18/// Total heap size in bytes (4 MiB).
19static HEAP_SIZE: usize = 0x400_000;
20
21/// The global allocator instance; empty until [`init`].
22#[global_allocator]
23static ALLOCATOR: LockedHeap = LockedHeap::empty();
24
25/// Map the heap virtual address range to physical frames and initialize the allocator.
26///
27/// # Panics
28/// Panics with [`PanicCode::OutOfMemory`] if the PMM cannot satisfy any frame allocation.
29pub fn init(pmm: &Pmm, vmm: &Vmm) {
30    unsafe {
31        for page in 0..(HEAP_SIZE / FRAME_SIZE as usize) {
32            let phys_page = pmm.alloc().unwrap_or_else(
33                || kernel_panic(
34                    PanicCode::OutOfMemory,
35                    "Out of memory for heap",
36                )
37            );
38            vmm.map_page(
39                pmm,
40                HEAP_BASE_ADDRESS + (page * FRAME_SIZE as usize) as u64,
41                phys_page,
42                PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
43            );
44        }
45
46        ALLOCATOR.lock().init(HEAP_BASE_ADDRESS.as_mut_ptr::<u8>(), HEAP_SIZE);
47    }
48}