miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
Loading...
Searching...
No Matches
pmm.c File Reference
Include dependency graph for pmm.c:

Classes

struct  mb2_tag
struct  mb2_tag_mmap
struct  mb2_mmap_entry

Macros

#define MB2_TAG_MMAP   6
#define MULTIBOOT_MEMORY_AVAILABLE   1

Functions

static uint64_t align_up (uint64_t v, uint64_t align)
static void pmm_set_free (uint64_t frame_idx)
static void pmm_set_used (uint64_t frame_idx)
static void pmm_free_range (uint64_t base, uint64_t length)
void pmm_init (uint64_t mb_info_phys)
uint64_t pmm_alloc_frame (void)
void pmm_free_frame (uint64_t phys)
void pmm_ref_frame (uint64_t phys)
void pmm_unref_frame (uint64_t phys)
uint64_t pmm_alloc_contiguous (size_t n_frames)
void pmm_free_contiguous (uint64_t phys, size_t n_frames)
uint64_t pmm_free_count (void)
uint64_t pmm_total_count (void)

Variables

static uint8_t * g_pmm_bitmap = NULL
static uint64_t g_max_frames = 0
static uint64_t g_bitmap_bytes = 0
static uint8_t * g_pmm_refcount = NULL
static uint64_t g_refcount_bytes = 0
static uint64_t total_free = 0
static uint64_t total_frames = 0
static spinlock_t pmm_lock = SPINLOCK_INIT
uint64_t __image_end

Macro Definition Documentation

◆ MB2_TAG_MMAP

#define MB2_TAG_MMAP   6

◆ MULTIBOOT_MEMORY_AVAILABLE

#define MULTIBOOT_MEMORY_AVAILABLE   1

Function Documentation

◆ align_up()

uint64_t align_up ( uint64_t v,
uint64_t align )
inlinestatic
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_alloc_contiguous()

uint64_t pmm_alloc_contiguous ( size_t n_frames)

pmm_alloc_contiguous() - Allocate n_frames physically contiguous frames. @n_frames: Number of consecutive 4 KiB frames required (must be > 0).

Linear scan for the first run of n_frames consecutive free bits. O(n) in the bitmap size — suitable for infrequent DMA allocations.

Returns
: Physical address of the first frame, or 0 on failure.

pmm_alloc_contiguous() - Allocate @n_frames physically contiguous 4 KiB frames. @n_frames: Number of frames required (must be > 0 and a power of 2 for DMA use).

Linear bitmap scan — O(n). Suitable for infrequent DMA allocations (virtqueues, DMA buffers). For single-frame allocations prefer pmm_alloc_frame().

Returns
: Physical address of the first frame (PAGE_SIZE-aligned), or 0 on failure.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_alloc_frame()

uint64_t pmm_alloc_frame ( void )

pmm_alloc_frame() - Return the physical address of a free frame.

Linear scan of g_pmm_bitmap looking for any non-zero byte. Within the found byte, bit-scans to the lowest set bit, clears it (USED), and returns frame_idx * PAGE_SIZE.

Returns
: 4 KiB-aligned physical address, or 0 on OOM.

pmm_alloc_frame() - Allocate a free 4 KiB physical frame.

Scans the bitmap for the first non-zero byte (O(1) amortized), then finds the lowest set bit within it. Marks the frame USED (bit=0) and decrements the total_free counter. Frame 0 is never returned (permanently marked USED).

Context: May be called from any non-ISR context. Not ISR-safe.

Returns
: 4 KiB-aligned physical address of the allocated frame, or 0 on OOM (no free frames remain).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_free_contiguous()

void pmm_free_contiguous ( uint64_t phys,
size_t n_frames )

pmm_free_contiguous() - Return n_frames contiguous frames to the free pool. @phys: Physical address of the first frame (4 KiB-aligned). @n_frames: Number of frames to free.

pmm_free_contiguous() - Return @n_frames contiguous frames to the free pool. @phys: Physical address of the first frame (PAGE_SIZE-aligned). @n_frames: Number of frames to release.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_free_count()

uint64_t pmm_free_count ( void )

pmm_free_count() - Return the number of free frames.

pmm_free_count() - Query the number of currently free physical frames.

Returns the total_free counter maintained incrementally by pmm_alloc_frame and pmm_free_frame. O(1) — does not scan the bitmap.

Returns
: Number of free 4 KiB frames available for allocation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_free_frame()

void pmm_free_frame ( uint64_t phys)

pmm_free_frame() - Mark a physical frame as free. @phys: Physical address of frame (4 KiB-aligned).

Guards against double-free: if the bit is already set, returns without modifying total_free.

pmm_free_frame() - Return a physical frame to the free pool. @phys: Physical address of the frame to free (must be 4 KiB-aligned).

Marks the frame FREE (bit=1) and increments total_free. Guards against double-free: if the frame is already free, the call is a no-op. Frame 0 must never be freed (permanently reserved).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_free_range()

void pmm_free_range ( uint64_t base,
uint64_t length )
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_init()

void pmm_init ( uint64_t mb_info_phys)

pmm_init() - Parse Multiboot 2 memory map and initialise the bitmap. @mb_info_phys: Physical address of MB2 struct; KERNEL_VMA added internally.

Two-pass init: Pass 1 — scan mmap to find the highest available physical address, then size and place the bitmap in physical RAM right after the kernel image (within the boot identity map, so the virtual address phys+KERNEL_VMA is immediately valid). Pass 2 — mark available regions free; mark kernel+bitmap frames used.

For a 64 MiB VM the bitmap is ~2 KiB instead of the 128 KiB that a static 4 GiB-ceiling array would require.

pmm_init() - Initialise the physical memory manager from Multiboot 2 info. @mb_info_phys: Physical address of the Multiboot 2 information structure.

Parses memory map tags from the Multiboot 2 structure to identify available RAM regions. Marks all available frames FREE in the bitmap (bit=1 means FREE). Explicitly marks frame 0 as USED. Kernelimage frames are also marked USED to prevent the PMM from returning kernel memory.

Context: Must be called once at boot before any call to pmm_alloc_frame.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_ref_frame()

void pmm_ref_frame ( uint64_t phys)

pmm_ref_frame() - Add an extra owner to an already-allocated frame.

pmm_ref_frame() - Add an extra owner to an already-allocated frame. @phys: Physical address of the frame (must have been returned by pmm_alloc_frame(), which starts every frame's refcount at 1).

Used when a frame becomes shared between two page tables (fork CoW: a read-only text page or a CoW-pending writable page shared between parent and child). Increments the frame's refcount; does not touch the bitmap.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_set_free()

void pmm_set_free ( uint64_t frame_idx)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_set_used()

void pmm_set_used ( uint64_t frame_idx)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_total_count()

uint64_t pmm_total_count ( void )

pmm_total_count() - Query the total number of physical frames discovered at boot.

Returns total_frames, incremented once per frame during pmm_init(). Does not change after boot. O(1).

Returns
: Total 4 KiB frame count (all usable RAM, including kernel-reserved frames).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pmm_unref_frame()

void pmm_unref_frame ( uint64_t phys)

pmm_unref_frame() - Drop one owner of a frame; frees it at refcount 0.

pmm_unref_frame() - Drop one owner of a frame; frees it at refcount 0. @phys: Physical address of the frame.

Decrements the frame's refcount. If it reaches 0, the frame is returned to the free pool exactly as pmm_free_frame() would. Safe to call on a frame with refcount 1 (behaves like pmm_free_frame()) — this is the normal case for private (non-CoW-shared) pages.

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ __image_end

uint64_t __image_end
extern

◆ g_bitmap_bytes

uint64_t g_bitmap_bytes = 0
static

◆ g_max_frames

uint64_t g_max_frames = 0
static

◆ g_pmm_bitmap

uint8_t* g_pmm_bitmap = NULL
static

◆ g_pmm_refcount

uint8_t* g_pmm_refcount = NULL
static

◆ g_refcount_bytes

uint64_t g_refcount_bytes = 0
static

◆ pmm_lock

spinlock_t pmm_lock = SPINLOCK_INIT
static

◆ total_frames

uint64_t total_frames = 0
static

◆ total_free

uint64_t total_free = 0
static