Virtual Memory Manager (VMM)
4-Level Paging and Memory Translation
Overview
The Virtual Memory Manager handles the translation between virtual addresses (what programs see) and physical addresses (actual RAM locations). AOS uses 4-level paging for 64-bit address space management.
Why Virtual Memory?
| Problem | Solution |
|---|---|
| Memory isolation | Each process has isolated address space |
| Large address space | 48-bit virtual space (256TB) for 64-bit systems |
| Flexible allocation | Physical RAM can be fragmented; virtual is contiguous |
| Higher-half kernel | Kernel mapped to high addresses separate from user code |
| Memory protection | Page-level read/write/execute permissions |
4-Level Page Table Structure
64-bit virtual addresses are divided into 5 parts:
Virtual Address (48-bit significant part) 63-48: Sign extension
(copies bit 47) 47-39: PML4 (Page Map Level 4) index - 9 bits 38-30:
PDPT (Page Directory Pointer Table) - 9 bits 29-21: PD (Page
Directory) index - 9 bits 20-12: PT (Page Table) index - 9 bits 11-0:
Offset within 4KB page - 12 bits
Page Table Entry (PTE)
Each page table entry is 64 bits:
0-11: Reserved
12-51: Physical frame address (40 bits)
52-61: Available (software)
62: NX (No Execute)
63: Bit 51 of address / various flags
Page Flags
// Common flags
#define PAGE_PRESENT (1UL << 0) // In physical memory
#define PAGE_WRITE (1UL << 1) // Writable
#define PAGE_USER (1UL << 2) // Usermode accessible
#define PAGE_NOCACHE (1UL << 4) // No caching
#define PAGE_ACCESSED (1UL << 5) // CPU set on access
#define PAGE_DIRTY (1UL << 6) // CPU set on write
#define PAGE_GLOBAL (1UL << 8) // Global (not flushed)
#define PAGE_NX (1UL << 63) // No Execute
Kernel Memory Layout
AOS maps memory as:
Virtual Address Space: 0x0000000000000000 - 0x00007FFFFFFFFFFF User
space (optional) 0x0000800000000000 - 0xFFFF7FFFFFFFFFFF Canonical
hole (invalid) 0xFFFF800000000000 - 0xFFFFFFFFFFFFFFFF Kernel space
(higher half) │ ├─ 0xFFFF800000000000 - 0xFFFF800000000000+1GB │
(Identity mapping / bootloader region) │ ├─ 0xFFFF800000100000 -
0xFFFF800007FFFFFF │ (Kernel code and data) │ └─ 0xFFFF800008000000 -
Higher addresses (Kernel heap, page tables, kernel stack)
TLB (Translation Lookaside Buffer)
The TLB is CPU cache of recent translations. After modifying page tables, we must flush relevant entries:
// Flush single TLB entry
static inline void tlb_flush_entry(uint64_t virt) {
asm volatile("invlpg (%0)" ::"r"(virt) : "memory");
}
// Flush entire TLB
static inline void tlb_flush_all(void) {
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
asm volatile("mov %0, %%cr3" ::"r"(cr3));
}
Key Features
- ✓ 4-level paging translates 48-bit virtual to physical
- ✓ 4KB pages are standard; 2MB/1GB pages save memory
- ✓ Higher-half kernel separates kernel from user space
- ✓ TLB invalidation needed after page table changes
- ✓ Page flags control access (read/write/execute)
- ✓ Supports demand paging and lazy allocation