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:
- Track Used/Free Pages - Know which physical addresses are available
- Prevent Conflicts - Ensure no two structures use the same memory
- Support Virtual Memory - Provide pages for page tables and data
- 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:
- Bit = 0: Page is free
- Bit = 1: Page is in use
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