# Paging Subsystem ## Overview The paging subsystem manages virtual memory using the x86 two-level paging scheme (no PAE). It provides identity mapping for all physical memory and a kernel heap region for dynamic virtual page allocation. ## Architecture ### Page Table Structure x86 32-bit paging uses two levels: | Level | Entries | Each Entry Maps | Total Coverage | |---|---|---|---| | Page Directory | 1024 | 4 MiB (one page table) | 4 GiB | | Page Table | 1024 | 4 KiB (one page) | 4 MiB | Each entry is a 32-bit value containing a 20-bit physical page frame number and 12 bits of flags. ### Identity Mapping During initialization, all detected physical memory is identity-mapped (virtual address = physical address). This is done in two phases: 1. **Static mapping (first 16 MiB):** Four page tables are statically allocated in BSS. This avoids a chicken-and-egg problem since the PMM bitmap itself resides in this region. 2. **Dynamic mapping (above 16 MiB):** Additional page tables are allocated from the PMM *before* paging is enabled (so physical addresses are still directly accessible). These cover all remaining detected physical memory. ### Kernel Heap The kernel heap region occupies virtual addresses `0xD0000000` through `0xF0000000` (768 MiB). When `paging_alloc_page()` is called: 1. A physical page is allocated from the PMM. 2. A page table entry is created mapping the next free virtual address to the physical page. 3. The virtual address is returned. When `paging_free_page()` is called: 1. The physical address is looked up via the page table entry. 2. The virtual mapping is removed. 3. The physical page is returned to the PMM. ### TLB Management - Single-page invalidations use `invlpg`. - Full TLB flushes use CR3 reload. ## API ```c void init_paging(void); void paging_map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags); void paging_unmap_page(uint32_t vaddr); void *paging_alloc_page(void); void paging_free_page(void *vaddr); uint32_t paging_get_physical(uint32_t vaddr); ``` ### Flags | Flag | Value | Meaning | |---|---|---| | `PAGE_PRESENT` | 0x001 | Page is present in memory | | `PAGE_WRITE` | 0x002 | Page is writable | | `PAGE_USER` | 0x004 | Page is user-accessible (ring 3) | ## Key Files - `src/paging.c` / `src/paging.h` — Implementation and API. - `src/pmm.c` / `src/pmm.h` — Physical page allocation backing. ## Design Decisions - **No higher-half kernel yet:** The kernel runs at its physical load address (1 MiB) with identity mapping. Higher-half mapping (0xC0000000) can be added later without changing the paging API. - **Static + dynamic page tables:** The first 16 MiB uses BSS-allocated tables to bootstrap, while memory above 16 MiB uses PMM-allocated tables. This keeps BSS usage bounded at ~16 KiB regardless of total RAM. - **Sequential heap allocation:** The heap grows upward linearly. No free-list reuse of freed virtual addresses is implemented yet.