Skip to main content
The Physical Memory Manager (PMM) is responsible for tracking and allocating 4 KiB physical pages across the identity-mapped first 1024 MiB of physical address space. It uses a bitmap-backed allocator, where each bit represents one 4 KiB page. Before you can call any allocation function, you must initialize the PMM with the total available RAM and the end address of the kernel image so that kernel memory is correctly marked reserved.

Data Types

The pmm_stats_t struct holds a snapshot of PMM counters at the moment pmm_get_stats is called. Its definition from mvh/memory.h is:

Functions

pmm_init

Initializes the Physical Memory Manager. You must call this function exactly once, before any call to pmm_alloc_pages, typically as one of the first steps in your kernel entry point. The PMM marks all pages occupied by the kernel image and its own bitmap as reserved so they are never returned to callers.
uint64_t
required
Total usable RAM in kibibytes, as reported by the bootloader (for example, from a Multiboot2 memory map). The PMM caps its working range at the identity-mapped first 1024 MiB (1,048,576 KiB); any value above this is silently clamped.
uintptr_t
required
Physical address of the first byte beyond the end of the loaded kernel image. All pages from physical address 0 up to and including the page containing kernel_end - 1 are marked reserved and will never be allocated. Pass the value of the linker-exported _kernel_end symbol here.

pmm_alloc_pages

Allocates a run of count physically contiguous 4 KiB pages and returns a pointer to the first page. The returned pointer is a direct physical address within the identity-mapped region, so you can use it for both physical and virtual access without any additional translation. The PMM searches for the first sufficiently large contiguous free run in its bitmap.
uint32_t
required
Number of contiguous 4 KiB pages to allocate. Must be greater than zero. Requesting more pages than are currently free, or requesting a run that cannot be satisfied contiguously, returns NULL.
void *
Pointer to the first byte of the allocated region on success, or NULL if the allocation fails (insufficient free pages, no contiguous run of the requested length, or the PMM has not been initialized). The returned pointer is always page-aligned (a multiple of 4096).
All allocated pages are physically contiguous. If you need, for example, 16 KiB of DMA-safe memory, pass count = 4 and you are guaranteed to receive four consecutive pages with no gaps.

pmm_free_pages

Returns a previously allocated run of pages to the free pool. You must pass exactly the same address and count that were returned or used in the corresponding pmm_alloc_pages call. Partial frees and double-frees produce undefined behavior.
void *
required
The pointer that was returned by pmm_alloc_pages. Must be page-aligned and within the identity-mapped region. Passing an unaligned, out-of-range, or already-freed address is undefined behavior.
uint32_t
required
The number of pages to free. This value must exactly match the count argument that was passed to the pmm_alloc_pages call that produced address. Passing a larger or smaller value corrupts the bitmap.
The PMM does not perform double-free detection. Freeing the same range twice silently corrupts the bitmap and will lead to two callers receiving overlapping physical memory. Always track allocation lifetimes carefully at the call site.

pmm_get_stats

Fills the pmm_stats_t structure pointed to by stats with a consistent snapshot of the PMM’s current counters. Use this function to monitor physical memory pressure or to produce diagnostic output.
pmm_stats_t *
required
Pointer to a caller-allocated pmm_stats_t struct. Must not be NULL. All fields are overwritten on return.
uint64_t
Total number of 4 KiB pages visible to the PMM (derived from memory_kib at pmm_init time, capped at 1024 MiB).
uint64_t
Number of pages currently allocated by callers (excludes reserved pages).
uint64_t
Number of pages currently available for allocation.
uint64_t
Number of pages permanently reserved for the kernel image, the PMM bitmap, and other non-allocatable regions.
uint64_t
Cumulative count of pmm_alloc_pages calls since pmm_init.
uint64_t
Cumulative count of pmm_free_pages calls since pmm_init.
uint64_t
Cumulative count of pmm_alloc_pages calls that returned NULL.
uint64_t
The highest value used_pages has ever reached since pmm_init. Useful for capacity-planning.

pmm_self_test

Runs the PMM’s built-in self-test suite. The test allocates and frees pages in various patterns to verify bitmap correctness, contiguous-run detection, and stat accounting. Call this once during early kernel initialization to validate PMM integrity on a new platform or after any change to PMM internals.
int
0 if all self-test cases pass. A non-zero value indicates the specific sub-test that failed; check the kernel serial log for a human-readable description.
Run pmm_self_test immediately after pmm_init in debug builds. It is safe to run against live PMM state because the test allocates and fully restores any pages it touches before returning.

Usage Example

The following example shows the canonical alloc → use → free pattern, along with how to inspect PMM statistics.