kernel/mm/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::arch::x86_64::mm::vmm::page_type::PageType;
8use crate::lib::addr::VirtAddr;
9use crate::lib::panic::kernel_panic;
10use crate::lib::panic_codes::PanicCode;
11use crate::mm::vmm::{traits::VmmPaging, Vmm};
12use crate::state::kstate::KSTATE;
13use linked_list_allocator::LockedHeap;
14use x86_64::structures::paging::PageTableFlags;
15
16// TODO: redo heap allocator properly
17
18/// First virtual address of the heap region (higher-half kernel space).
19const HEAP_BASE_ADDRESS: VirtAddr = VirtAddr::new(0xffff_f800_0000_0000);
20
21/// Total heap size in bytes (4 MiB).
22const HEAP_SIZE: usize = 0x400_000;
23
24/// The global allocator instance; empty until [`init`].
25#[global_allocator]
26static ALLOCATOR: LockedHeap = LockedHeap::empty();
27
28/// Map the heap virtual address range to physical frames and initialize the allocator.
29///
30/// # Panics
31/// Panics with [`PanicCode::OutOfMemory`] if the PMM cannot satisfy any frame allocation.
32pub fn init(kernel_root_page: VirtAddr) {
33 // Safety: the PMM gets initialized before the heap in mm_init
34 let mut pmm = unsafe { KSTATE.mm.pmm().lock() };
35
36 const HUGE_PAGE_SIZE: usize = 0x200_000; // 2 MiB
37 const NUM_HUGE_PAGES: usize = HEAP_SIZE / HUGE_PAGE_SIZE; // 2
38
39 for page in 0..NUM_HUGE_PAGES {
40 let phys = pmm.alloc(9).unwrap_or_else(
41 || kernel_panic(
42 PanicCode::OutOfMemory,
43 "Out of memory for heap"
44 )
45 );
46
47 // Safety: kernel_root_page is the valid kernel PML4, phys is a valid frame that was
48 // just mapped
49 unsafe {
50 if Vmm::map_page(
51 &mut pmm,
52 kernel_root_page,
53 HEAP_BASE_ADDRESS + (page * HUGE_PAGE_SIZE) as u64,
54 phys,
55 PageType::HugePage2MiB, // TODO: no arch specific page type here
56 PageTableFlags::WRITABLE,
57 ).is_err() {
58 kernel_panic(
59 PanicCode::OutOfMemory,
60 "Could not map one or more kernel heap pages, out of memory"
61 )
62 }
63 }
64 }
65
66 // Safety: boot was never called before, the given heap base addr is valid, static and not
67 // used for anything else
68 unsafe {
69 ALLOCATOR.lock().init(HEAP_BASE_ADDRESS.as_mut_ptr::<u8>(), HEAP_SIZE);
70 }
71}