- Created two-level x86 paging (page directory + page tables) with 4 KiB pages.
- Identity maps all detected physical memory in two phases:
1) Static: first 16 MiB using 4 BSS-allocated page tables (avoids
chicken-and-egg with PMM bitmap in BSS).
2) Dynamic: memory above 16 MiB using PMM-allocated page tables,
created before paging is enabled so physical addresses still work.
- Provides kernel heap at 0xD0000000–0xF0000000 for virtual page allocation.
- API: paging_map_page, paging_unmap_page, paging_alloc_page, paging_free_page,
paging_get_physical.
- Added pmm_get_memory_size() to expose detected RAM for paging init.
- Kernel tests paging by allocating a virtual page, writing 0xDEADBEEF, and
reading it back, then freeing it.
- Added documentation in docs/paging.md.
Tested: boots and passes paging test with both 4 MiB and 128 MiB RAM in QEMU.
76 lines
2.9 KiB
Markdown
76 lines
2.9 KiB
Markdown
# 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.
|