diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-10-16 02:39:56 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-10-16 02:39:56 +0800 |
| commit | 8cace3f05003c6cb4d38c36890055f03151c2ad4 (patch) | |
| tree | aa739deaac0266f17c4e91b333957501cb1ea2e9 /docs/specs/vmm.md | |
| parent | 3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee (diff) | |
| download | lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.gz lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.xz | |
Remove old code
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
Diffstat (limited to 'docs/specs/vmm.md')
| -rw-r--r-- | docs/specs/vmm.md | 158 |
1 files changed, 0 insertions, 158 deletions
diff --git a/docs/specs/vmm.md b/docs/specs/vmm.md deleted file mode 100644 index 7492a02..0000000 --- a/docs/specs/vmm.md +++ /dev/null @@ -1,158 +0,0 @@ -# 虚拟内存管理器 (Virtual Memory Manager) - -## 1. 目标 (Objective) - -为 LumeOS 管理虚拟地址空间。本模块分两个阶段实现: - -- **Phase 1(本文档重点):** - 1. 在 `vmm_init()` 中建立精细化的内核页表(4KB 粒度、精确权限)。 - 2. 实现基于 Rbtree 和 Slab 的 VMA (Virtual Memory Area) 区间树以管理用户态内存。 - 3. 实现架构无关的按需分页 (Demand Paging) 模拟接口。 -- **Phase 2(未来):** 将 VMM 的按需分页逻辑绑定到真实的 Trap 异常中断系统,并引入进程 (Process/Task) 关联和基于硬件触发的缺页异常处理。 - -采用 pmap(Physical Map)分层模型:MI 层管理地址空间布局逻辑,MD 层(`arch/riscv/mm/pmap.cc`)封装 SV39 页表硬件操作。 - -## 2. 前置依赖 (Dependencies) - -- **全局初始化契约 (`global_init.md`):** `vmm_init()` 在 `slab_init()` 和 `fdt_unflatten()` 之后、`trap_init()` 之前被 BSP 调用。 -- **物理内存契约 (`pmm.md`):** 依赖 `pmm_alloc_frame()` 分配页表页。 -- **Slab 分配器契约 (`slab.md`):** Phase 2 依赖 `kmalloc` 创建 VMA 对象。 -- **架构抽象契约 (`arch_abstraction.md`):** 依赖 `arch::mmu::set_page_table()`, `arch::mmu::flush_tlb_all()` 切换和刷新页表。 -- **链接脚本契约 (`linker_and_entry.md`):** 依赖 `_stext/_etext`, `_srodata/_erodata`, `_sdata/_edata`, `_sbss/_ebss`, `_kernel_end` 确定各段边界。 - -## 3. 核心数据结构 (Data Structures) - -### 3.1 SV39 页表项 (PTE) 格式 - -``` -63 54 53 28 27 19 18 10 9 8 7 6 5 4 3 2 1 0 -+---------+----------+----------+----------+----+-+-+-+-+-+-+-+-+ -| Reserved| PPN[2] | PPN[1] | PPN[0] |RSW |D|A|G|U|X|W|R|V| -| (10) | (26) | (9) | (9) |(2) |1|1|1|1|1|1|1|1| -+---------+----------+----------+----------+----+-+-+-+-+-+-+-+-+ -``` - -权限位常量: - -```cpp -namespace pmap { - inline constexpr uint64 PTE_V = 1 << 0; // Valid - inline constexpr uint64 PTE_R = 1 << 1; // Read - inline constexpr uint64 PTE_W = 1 << 2; // Write - inline constexpr uint64 PTE_X = 1 << 3; // Execute - inline constexpr uint64 PTE_U = 1 << 4; // User-accessible - inline constexpr uint64 PTE_G = 1 << 5; // Global - inline constexpr uint64 PTE_A = 1 << 6; // Accessed - inline constexpr uint64 PTE_D = 1 << 7; // Dirty -} -``` - -### 3.2 pmap 接口 (MD 层, namespace 函数) - -遵循 `00_conventions.md` 的多态策略——pmap 为极热路径,使用 namespace 函数 + 编译期链接。 - -```cpp -// 定义于 arch/riscv/mm/pmap.h (arch 私有头) 和 mm/pmap.h (MI 接口) -namespace pmap { - // 分配并初始化一个新的根页表,返回其物理地址。 - // 失败返回 0。 - uint64 create(); - - // 销毁一个页表及其所有子页表页。 - void destroy(uint64 root_pa); - - // 建立映射:va -> pa,权限为 perm。 - // 自动分配中间页表页。 - // 返回 0 成功,负错误码失败。 - int map(uint64 root_pa, uint64 va, uint64 pa, uint64 perm); - - // 解除 va 处的映射。 - void unmap(uint64 root_pa, uint64 va); - - // 查询 va 对应的 pa。成功返回 true 并写入 *pa_out。 - bool lookup(uint64 root_pa, uint64 va, uint64* pa_out); - - // 将 root_pa 写入 satp 并刷新 TLB。 - void activate(uint64 root_pa); -} -``` - -### 3.3 内核地址空间布局 - -`vmm_init()` 建立的精细内核映射: - -``` -Virtual Address Physical Address Perm Description -───────────────────────────────────────────────────────────────────── -arch::kVAOffset + 0x80200000 0x80200000 R-X .text (代码段) -arch::kVAOffset + _srodata _srodata_pa R-- .rodata (只读数据) -arch::kVAOffset + _sdata _sdata_pa RW- .data + .bss -arch::kVAOffset + frame_map_pa frame_map_pa RW- PMM frame_map 数组 -arch::kVAOffset + 0x10000000 0x10000000 RW- UART MMIO -arch::kVAOffset + 0x0C000000 0x0C000000 RW- PLIC MMIO -arch::kVAOffset + mem_end ... RW- 剩余物理内存 (到 mem_end) -``` - -## 4. 公共 API (Public APIs) - -### 4.1 Phase 1 API - -```cpp -// 初始化内核页表,替代 early_pgdir。 -// 1. 分配新根页表 -// 2. 按段权限映射内核各段 -// 3. 映射 MMIO 区域 -// 4. 激活新页表 -// 5. 旧的 early_pgdir 恒等映射自动失效 -void vmm_init(); - -// AP 切换到 BSP 建好的内核页表 -void vmm_init_ap(); -``` - -### 4.2 Phase 2 API (未来) - -```cpp -// 暂为 stub,Phase 2 实现 -int vmm_map_user(uint64 root_pa, uint64 va, uint64 len, uint64 perm); -int vmm_unmap_user(uint64 root_pa, uint64 va, uint64 len); -int vmm_handle_page_fault(uint64 root_pa, uint64 fault_addr, uint64 cause); -uint64 vmm_clone(uint64 parent_root_pa); -``` - -## 5. 并发与锁契约 (Concurrency & Locks) - -- **Phase 1:** `vmm_init()` 在 BSP 单核期执行,无需锁。 -- **pmap 锁:** 每个根页表关联一把 Spinlock(Phase 2 在 AddressSpace 结构中)。多核操作同一页表必须持有此锁。 -- **TLB Shootdown:** Phase 1 仅有内核页表且在单核期建立,无需 shootdown。Phase 2 需实现。 - -## 6. 错误路径 (Error Paths) - -- `pmap::create()` 或 `pmap::map()` 中 `pmm_alloc_frame()` 失败 → `kernel_panic()`(内核页表映射失败不可恢复)。 -- `vmm_init()` 中任何映射步骤失败 → `kernel_panic()`。 - -## 7. 状态机 / 时序图 (State Machine / Sequence) - -### 7.1 vmm_init 时序 - -``` -[kernel_main on BSP, after slab_init + fdt_unflatten] - │ - ├─> 1. root_pa = pmap::create() // 分配新根页表 - │ - ├─> 2. 映射内核 .text 段 (RX) - │ for (pa = _stext_pa; pa < _etext_pa; pa += PAGE_SIZE) - │ pmap::map(root_pa, pa + arch::kVAOffset, pa, PTE_R|PTE_X|PTE_G) - │ - ├─> 3. 映射 .rodata 段 (R-) - ├─> 4. 映射 .data + .bss 段 (RW) - ├─> 5. 映射 frame_map 区域 (RW) - ├─> 6. 映射剩余物理内存 (RW) - ├─> 7. 映射 MMIO: UART 0x10000000, PLIC 0x0C000000 (RW) - │ - ├─> 8. pmap::activate(root_pa) // 写 satp, sfence.vma - │ └─ 此刻 early_pgdir 的恒等映射失效 - │ └─ 代码继续执行(因为高半区映射已建立) - │ - └─> 9. 保存 root_pa 到全局变量 g_kernel_pgtbl -``` |
