šŸ“š AOS Docs

Physical Memory Manager (PMM)

Bitmap-Based Memory Page Allocation

Overview

The Physical Memory Manager (PMM) is responsible for tracking and allocating physical RAM. AOS uses a bitmap allocation strategy to efficiently manage memory pages.

Purpose

The PMM solves these critical problems:

  1. Track Used/Free Pages - Know which physical addresses are available
  2. Prevent Conflicts - Ensure no two structures use the same memory
  3. Support Virtual Memory - Provide pages for page tables and data
  4. Efficient Allocation - Quick operations for fast boot and runtime

Memory Layout After Boot

0x0000 - 0x1000 [Null Page + Real Mode IDT] 0x1000 - 0x80000 [Bootloader + Kernel code/data] 0x80000 - ... [Bitmap] ... - 0xFF000000 [Available for allocation]

Bitmap Allocation Strategy

How It Works

Each bit in a bitmap represents one 4KB page:

Memory Calculation

Total RAM = 4GB (32-bit addressing limit for now)
Page size = 4KB (2^12 bytes)
Total pages = 4GB / 4KB = 1,048,576 pages
Bitmap size = 1,048,576 bits / 8 = 131,072 bytes = 128KB

Benefits

Advantage Explanation
Fast Bit operations are CPU native instructions
Space Efficient 1 byte tracks 8 pages (128KB per 4GB)
Simple No complex data structures needed
Aligned Works perfectly with 4KB page size

PMM Implementation

Core Data Structures

// From include/pmm.h
typedef unsigned char byte;

extern byte* bitmap;         // Pointer to bitmap in memory
extern uint32_t bitmap_size; // Size of bitmap in bytes
extern uint32_t max_pages;   // Total pages addressable
extern uint32_t used_pages;  // Pages currently allocated

Key Functions

void pmm_init(uint32_t magic, multiboot_info_t* mbd);
void* pmm_alloc_page(void);
void pmm_free_page(void* page);
int pmm_test_page(uint32_t page_num);
void pmm_set_page(uint32_t page_num);
void pmm_unset_page(uint32_t page_num);
uint32_t pmm_get_total_memory_kb(void);

Bitmap Bit Operations

// Mark a page as used
void pmm_set_page(uint32_t page_num) {
    uint32_t byte_idx = page_num / 8;      // Which byte?
    uint32_t bit_idx  = page_num % 8;      // Which bit in byte?
    
    bitmap[byte_idx] |= (1 << bit_idx);    // Set the bit
    used_pages++;
}

// Mark a page as free
void pmm_unset_page(uint32_t page_num) {
    uint32_t byte_idx = page_num / 8;
    uint32_t bit_idx  = page_num % 8;
    
    bitmap[byte_idx] &= ~(1 << bit_idx);   // Clear the bit
    used_pages--;
}

// Check if page is in use
int pmm_test_page(uint32_t page_num) {
    uint32_t byte_idx = page_num / 8;
    uint32_t bit_idx  = page_num % 8;
    
    return (bitmap[byte_idx] >> bit_idx) & 1;
}

Page Allocation Process

Finding Free Pages

void* pmm_alloc_page(void) {
    // Find first free bit in bitmap
    for (uint32_t byte_idx = 0; byte_idx < bitmap_size; byte_idx++) {
        if (bitmap[byte_idx] != 0xFF) {  // If not all bits set
            // Find first 0 bit in this byte
            for (uint8_t bit_idx = 0; bit_idx < 8; bit_idx++) {
                if (!(bitmap[byte_idx] & (1 << bit_idx))) {
                    // Found free bit!
                    uint32_t page_num = byte_idx * 8 + bit_idx;
                    pmm_set_page(page_num);
                    
                    // Return physical address
                    return (void*)(page_num * PAGE_SIZE);
                }
            }
        }
    }
    
    return NULL;  // No free pages!
}

Performance Characteristics

Operation Time Complexity Details
Allocate page O(n) Linear scan worst case, avg ~O(1)
Free page O(1) Single bit operation
Test page O(1) Single bit test
Allocate contiguous O(n²) Worst case scans twice

šŸ’” Optimization: Hint Pointer

Better implementations maintain a "hint" pointer to last free page for faster allocation on the next request. This typically improves average performance to O(1).

Integration with Virtual Memory

PMM and VMM work together seamlessly:

Virtual Memory Manager (VMM) ↓ "I need a page for page table" ↓ Physical Memory Manager (PMM) ↓ "Here's physical address 0x200000" ↓ VMM maps to virtual address 0xFFFF800000200000

Key Takeaways

  • āœ“ Bitmap tracks used/free pages efficiently
  • āœ“ Simple bit operations for allocation/deallocation
  • āœ“ Calculated from bootloader memory map
  • āœ“ Minimal overhead (128 KB for 4GB RAM)
  • āœ“ O(1) or O(n) operations sufficient for OS
  • āœ“ Foundation for virtual memory manager
  • āœ“ Statistic tracking for debugging