📚 AOS Docs

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