硬件分页机制原理

发布时间:2026/7/19 16:59:00

硬件分页机制原理 硬件分页机制原理概述分页Paging是 CPU 内存管理单元MMU提供的一种地址转换机制将程序使用的虚拟地址Virtual Address转换为物理内存中的物理地址Physical Address。分页机制是所有现代操作系统实现虚拟内存、进程隔离、页面换出等特性的硬件基础。本文涵盖 x86 32-bit非PAE、x86 PAE物理地址扩展、x86-644 级页表和 ARM 四种分页模式并以 ReactOS 源码中的硬件定义为例。1. 基础概念1.1 页面Page物理内存被划分为固定大小的块称为物理页帧Page Frame。x86/x64 架构的标准页面大小为4KB0x1000 字节此外还支持大页面2MB、4MB、1GB。#definePAGE_SIZE0x1000// 4KB#definePAGE_SHIFT12// 页内偏移的位数#definePAGE_MASK0xFFFFF000// 页基址掩码清零低12位1.2 页表Page Table页表是存储在内存中的层级数据结构MMU 通过遍历页表树将虚拟地址转换为物理地址。每个页表项PTE/PDE通常包含物理页帧号PFN / Page Frame Number权限位可读/可写/可执行/用户模式状态位有效Present/已访问Accessed/已修改Dirty缓存属性可缓存/禁止缓存/写合并/写透1.3 控制寄存器寄存器功能CR0PG 位位31启用分页PE 位位0启用保护模式CR2存储最近一次缺页异常的虚拟地址CR3页目录基址寄存器PDBR指向顶级的页表结构CR4PAE 位位5启用物理地址扩展PSE 位位4启用大页面PGE 位位7启用全局页面2. x86 32-bit 分页非 PAE2.1 寻址模式虚拟地址为 32 位物理地址为 32 位最大 4GB两级页表。31 22 21 12 11 0 ┌────────────┬────────────┬─────────────────┐ │ Directory │ Table │ Offset │ │ 10 bits │ 10 bits │ 12 bits │ └──────────────┴──────────────┴─────────────────┘顶级页目录Page Directory1024 个 PDE每个 32 位4 字节共 4KB次级页表Page Table1024 个 PTE每个 32 位4 字节共 4KB可寻址页数1024 × 1024 1,048,576 个页4GB2.2 地址转换流程CR3 ──→ Page Directory (4KB) │ │ Directory[31:22]10 位索引 ▼ PDE32位──→ Page Table (4KB) │ │ Table[21:12]10 位索引 ▼ PTE32位──→ Physical Page (4KB) │ │ Offset[11:0]12 位 ▼ 物理地址2.3 PDE/PTE 结构32位ReactOS 定义ntoskrnl/mm/i386/page.c// x86 32位 PTE 模板#definePTE_VALID0x1// 有效位Present位0#definePTE_READWRITE0x2// 可写R/W位1#definePTE_USER0x4// 用户模式U/S位2#definePTE_WRITETHROUGH0x8// 写透PWT位3#definePTE_DISABLE_CACHE0x10// 禁止缓存PCD位4#definePTE_ACCESSED0x20// 已访问A位5#definePTE_DIRTY0x40// 已修改D位6#definePTE_LARGEPAGE0x80// 大页面PS位7仅在 PDE 中有效#definePTE_GLOBAL0x100// 全局页面G位8#definePTE_PROTOTYPE0x400// 原型 PTE软件定义位10#definePTE_PROTECT_MASK0x612// 保护掩码位1,4,9// 32位 PTE 完整结构// 位 0: Present — 页面在物理内存中// 位 1: R/W — 0只读, 1读写// 位 2: U/S — 0超级用户, 1用户// 位 3: PWT — 写透缓存策略// 位 4: PCD — 禁止缓存// 位 5: A — MMU自动置位读/写时// 位 6: D — MMU自动置位写时// 位 7: PS — PDE中04KB页面, 14MB页面需 CR4.PSE1// 位 8: G — 全局页面TLB 不刷新// 位 9-11: Available — 操作系统可用// 位 12-31: PFN — 物理页帧号20位最大寻址 4GB//// 4MB 大页面CR4.PSE1, PDE.PS1// 位 12-31: PFN20位实际可寻址 4MB22位页帧号10位片内偏移ReactOS 中的保护掩码映射表externconstULONG_PTR MmProtectToPteMask[32];// 将 MM_* 保护常量转换为硬件 PTE 标志// 例如MM_READWRITE→设置 PTE_READWRITE,// MM_NOCACHE→设置 PTE_DISABLE_CACHE,// MM_EXECUTE→检查 NX 等externconstULONG MmProtectToValue[32];// 将 MM_* 保护常量转换为 NT API PAGE_* 常量// 例如MM_READONLY → PAGE_READONLY,// MM_READWRITE → PAGE_READWRITE3. x86 PAE 分页物理地址扩展3.1 概述PAEPhysical Address Extension将物理地址从 32 位扩展到 36 位使 x86 32 位系统最多可寻址64GB物理内存。虚拟地址仍为 32 位进程地址空间仍为 4GB。启用方式设置 CR4.PAE 1CR4 寄存器第 5 位3.2 寻址模式PAE 将页表从 2 级扩展到3 级31 30 29 21 20 12 11 0 ┌────────┬──────────┬──────────┬─────────────────┐ │ PDPT │ Directory│ Table │ Offset │ │ 2 bits │ 9 bits │ 9 bits │ 12 bits │ └────────┴──────────┴──────────┴─────────────────┘每一级的 PTE/PDE 从 32 位扩大为64 位8 字节。3.3 三级页表结构级别名称条目数条目大小总大小1页目录指针表PDPT48 字节32 字节CR3 指向2页目录PD5128 字节4KB3页表PT5128 字节4KB转换流程CR3 ──→ PDPT4个条目在 CR3 寄存器内部缓存 │ │ PDPT[31:30]2位索引选择4个中的一个 ▼ PDPTE ← 64位指向 PD │ │ PD[29:21]9位索引 ▼ PDE64位──→ PT 或 2MB 页面 │ │ PT[20:12]9位索引 ▼ PTE64位──→ 4KB 物理页面大页面PDE.PS 1 时PDE 直接指向 2MB 物理页面跳过页表级。ReactOS 中的 PAE 定义ntoskrnl/mm/i386/pagepae.c// PAE 专用常量#definePA_PRESENT0x001#definePA_READWRITE0x002#definePA_USER0x004#definePA_WRITETHROUGH0x008#definePA_CACHE_DISABLE0x010#definePA_ACCESSED0x020#definePA_DIRTY0x040#definePA_LARGEPAGE0x080// 2MB 页面#definePA_GLOBAL0x100#definePA_PROTOTYPE0x400// 软件定义#definePA_NX0x8000000000000000ULL// 第63位不可执行// PAE PDE/PTE 结构64位// 位 0: Present// 位 1: R/W// 位 2: U/S// 位 3-4: PWT, PCD// 位 5: Accessed// 位 6: Dirty// 位 7: PS — PDE中0→指向 PT, 1→2MB 页面// 位 8: Global// 位 9-11: Available// 位 12-35: PFN24位 → 36位物理地址寻址 64GB// 低 12 位补零得到 36 位物理地址// 位 36-51: Reserved须为0// 位 52-62: Available// 位 63: NX — 不可执行// PAE 页目录指针表PDPT结构// CR3 指向 PDPT每个 PDPTE 指向一个页目录PD#definePAE_PDPT_ENTRIES4#definePAE_PAGE_TABLES4// 4个页目录每个对应 1GB 地址空间3.4 与 x86-64 的关系x86-64长模式启动时必须先启用 PAE。长模式下的页表是 PAE 的直接扩展在 PDPT 之上增加了 PML4 级。4. x86-64 分页4 级页表 / 长模式4.1 寻址模式虚拟地址为64 位但当前处理器只使用低48 位即 256TB 地址空间。高 16 位必须为符号扩展与位 47 相同。物理地址可达52 位当前典型实现为 40 或 48 位。4.2 四级页表结构47 39 38 30 29 21 20 12 11 0 ┌──────────┬──────────┬──────────┬──────────┬─────────────────┐ │ PML4 │ PDPT │ PD │ PT │ Offset │ │ 9 bits │ 9 bits │ 9 bits │ 9 bits │ 12 bits │ └──────────┴──────────┴──────────┴──────────┴─────────────────┘级别名称条目数条目大小总大小1PML4Page Map Level 45128 字节4KB2PDPTPage Directory Pointer Table5128 字节4KB3PDPage Directory5128 字节4KB4PTPage Table5128 字节4KB每个页表项 64 位每个页表 512 项 × 8 字节 4KB整体对齐。4 级页表的可寻址范围4KB 页面512⁴ 2³⁶ 个页覆盖 2³⁶ × 4KB 256TB2MB 页面跳过 PT 级512³ 2²⁷ 个页覆盖 512 GB1GB 页面跳过 PT 和 PD 级512² 2¹⁸ 个页覆盖 512 TB4.3 地址转换流程CR3 ──→ PML4 Table4KB │ │ PML4[47:39]9位索引 ▼ PML4E64位──→ PDPT4KB │ │ PDPT[38:30]9位索引 ▼ PDPTE64位──→ PD4KB │ │ PD[29:21]9位索引 ▼ PDE64位 │ ┌────────────┴────────────┐ │ PS0 │ PS1 ▼ ▼ PT4KB 2MB Physical Page │ │ PT[20:12]9位索引 ▼ PTE64位──→ 4KB Physical Page4.4 PML4E/PDPTE/PDE/PTE 结构64位来源Intel Manual Vol 3ReactOS mmtypes.hsdk/include/ndk/amd64/mmtypes.h// 64位页表项结构PML4E/PDPTE/PDE/PTE // 位 0: Present (P) // 位 1: R/W // 位 2: U/S // 位 3: PWT (Write-Through) // 位 4: PCD (Cache Disable) // 位 5: Accessed (A) — MMU 置位 // 位 6: Dirty (D) — MMU 置位PDE中2MB页面有效 // 位 7: PS (Page Size) — PML4E0; PDPTE: 1→1GB页; PDE: 1→2MB页 // 位 8: Global (G) — 仅在 PDE/PTE 中有效 // 位 9-11: Available — 操作系统可用如 ReactOS 用位10作原型PTE标志 // 位 12-51: PFN — 物理页帧号最多 52-1240位支持 1TB 物理内存 // 位 52-62: Available — 操作系统可用 // 位 63: NX (No-Execute) — 不可执行XD 位 // 4KB 页面的 PTE 格式 // 位 12-51: PFN40位物理地址低12补零 最大52位物理地址ReactOS amd64 定义sdk/include/ndk/amd64/mmtypes.htypedefstruct_MMPTE{union{ULONG_PTR Long;// 64位完整值HARDWARE_PTE Flush;// TLB 刷新用的硬件结构MMPTE_HARDWARE Hard;// 硬件 PTE 解释MMPTE_PROTOTYPE Proto;// 原型 PTE软件定义MMPTE_SOFTWARE Soft;// 软件 PTE请求零页等MMPTE_TRANSITION Trans;// 转换态 PTE页面在备用/修改列表MMPTE_SUBSECTION Subsect;// 子段 PTESection 映射MMPTE_LIST List;// 列表 PTE页表项链表}u;}MMPTE,*PMMPTE,MMPDE,*PMMPDE,// 页目录项MMPPE,*PMMPPE,// 页目录指针表项MMPXE,*PMMPXE;// PML4 项// x86-64 PTE 标志ReactOS miarm.h#definePTE_READONLY0x8000000000000000ULL// NX 位#definePTE_EXECUTE0x0000000000000000ULL#definePTE_EXECUTE_READPTE_EXECUTE// x64 上 EXECUTE 隐含 READ#definePTE_READWRITE0x8000000000000002ULL// NXR/W#definePTE_WRITECOPY0x8000000000000200ULL#definePTE_EXECUTE_READWRITE0x0000000000000002ULL#definePTE_EXECUTE_WRITECOPY0x0000000000000200ULL#definePTE_PROTOTYPE0x0000000000000400ULL#definePTE_VALID0x0000000000000001ULL#definePTE_ACCESSED0x0000000000000020ULL#definePTE_DIRTY0x0000000000000040ULL#definePTE_DISABLE_CACHE0x0000000000000010ULL#definePTE_WRITECOMBINED_CACHE0x0000000000000010ULL#definePTE_PROTECT_MASK0x8000000000000612ULL// 保护相关位掩码4.5 大页面模式页面大小所需页表级虚拟地址拆分4KBPML4 → PDPT → PD → PT4级999912 48位2MBPML4 → PDPT → PD3级99921 48位1GBPML4 → PDPT2级9930 48位5. ARM 分页5.1 二级页表ARMv7-A 架构使用二级页表31 20 19 12 11 0 ┌──────────┬──────────┬─────────────────┐ │ PDE │ PTE │ Offset │ │ 12 bits │ 8 bits │ 12 bits │ └──────────┴──────────┴─────────────────┘级别名称条目数条目大小说明1页目录Page Directory40964 字节覆盖 1MB/4KB 页面2页表Page Table2564 字节仅在 4KB 页面时使用页面大小选项ARMv7节Section1MB一级页表直接映射PDE.位10、位01粗页Large Page64KB二级页表16个4KB子页小页Small Page4KB二级页表ReactOS ARM 定义sdk/include/ndk/arm/mmtypes.htypedefstruct_MMPTE{union{ULONG_PTR Long;HARDWARE_PTE Flush;MMPTE_HARDWARE Hard;MMPTE_PROTOTYPE Proto;MMPTE_SOFTWARE Soft;MMPTE_TRANSITION Trans;MMPTE_SUBSECTION Subsect;MMPTE_LIST List;}u;}MMPTE,*PMMPTE;// ARM 页目录项typedefstruct_MMPDE{union{MMPDE_HARDWARE Hard;ULONG Long;}u;}MMPDE,*PMMPDE;// ARM PDE 硬件结构typedefunion_MMPDE_HARDWARE{ULONG Valid:1;ULONG LargePage:1;ULONG Buffered:1;ULONG Cached:1;ULONG NoExecute:1;ULONG Domain:4;ULONG Ecc:1;ULONG PageFrameNumber:22;}MMPDE_HARDWARE,*PMMPDE_HARDWARE;// ARM PTE 标志ReactOS miarm.h#definePTE_READONLY0x200#definePTE_PROTOTYPE0x400// 使用共享位注意ReactOS 的 ARM 分支中大部分页表操作为UNIMPLEMENTED存根ARM 架构的支持仍在开发中。6. TLB 与缓存管理6.1 转换后备缓冲区TLBTLBTranslation Lookaside Buffer是 MMU 内部的页表缓存存储最近使用的虚拟地址到物理地址的转换。每次内存访问时 CPU 先查 TLB命中则直接获得物理地址未命中才遍历页表page walk。TLB 刷新// x86 单 CPU TLB 刷新 — 使用 invlpg 指令使单个页面失效__invlpg(VirtualAddress);// x86 完整 TLB 刷新 — 重新加载 CR3 寄存器// CR3 写入操作会刷新所有非全局 TLB 条目asmvolatile(mov %0, %%cr3::r(NewCr3Value):memory);// 全局页面 — 设置 PTE_GLOBAL1TLB 刷新时不刷新这些条目#definePTE_GLOBAL0x100ReactOS PAE 模式的 TLB 刷新ntoskrnl/mm/i386/pagepae.c// 单处理器直接 invlpgMiFlushTlb(LinearAddress){__invlpg(LinearAddress);}// 多处理器通过 IPI 在所有 CPU 上执行刷新MiFlushTlbIpiRoutine(VOID){// 在 IPI 中断处理器中执行 TLB 刷新__invlpg(Thread-TlbFlushAddress);}6.2 页表结构缓存除了 TLB处理器还缓存页表项本身Paging-Structure Caches包括 PDE、PDPTE、PML4E 的缓存。当操作系统修改页表时必须使用invlpg或 CR3 切换使这些缓存失效。6.3 缓存属性位位含义缓存策略PCD0, PWT0Write-Back回写默认策略性能最高PCD0, PWT1Write-Through写透写入同时更新内存PCD1, PWT0Uncached非缓存用于 MMIO 设备寄存器PCD1, PWT1Uncached非缓存同上7. 分页模式对比特性32-bit非PAEPAEx86-64长模式虚拟地址宽度32 位32 位48 位扩展到 64物理地址宽度32 位36 位52 位最大物理内存4 GB64 GB4 PB页表级数234每级索引位数10102999999标准页面大小4KB4KB4KB大页面大小4MB2MB2MB第3级 / 1GB第2级PTE/PDE 大小32 位64 位64 位每页表条目数1024512512NX 支持否是位63是位63CR3 指向页目录页目录指针表PML4 表各架构的分页模式映射非PAE (2级): PAE (3级): x86-64 (4级): CR3 CR3 CR3 │ │ │ ▼ ▼ ▼ ┌──────┐ ┌──────┐ ┌──────┐ │ PD │ │ PDPT │ │ PML4 │ │1024个│ │ 4个 │ │512个 │ └──┬───┘ └──┬───┘ └──┬───┘ │ │ │ ▼ ▼ ▼ ┌──────┐ ┌──────┐ ┌──────┐ │ PT │ │ PD │ │ PDPT │ │1024个│ │512个 │ │512个 │ └──┬───┘ └──┬───┘ └──┬───┘ │ │ │ ▼ ▼ ▼ ┌──────┐ ┌──────┐ ┌──────┐ │ 4KB │ │ PT │ │ PD │ │ Page │ │512个 │ │512个 │ └──────┘ └──┬───┘ └──┬───┘ │ │ ▼ ▼ ┌──────┐ ┌──────┐ │ 4KB │ │ PT │ │ Page │ │512个 │ └──────┘ └──┬───┘ │ ▼ ┌──────┐ │ 4KB │ │ Page │ └──────┘8. ReactOS 中的页表自映射技巧x86 架构下ReactOS 利用页目录的最后一项指向页目录自身实现页表的虚拟可寻址性。这使得内核可以通过普通虚拟地址直接访问任意 PTE无需物理地址转换或临时映射。PD[1023] → PD 自身的物理地址 ← 自引用 PD[1022] → 超空间 PDE ← 临时物理页映射 PD[0..1021] → 进程页表项 ← 正常映射 通过 PTE_BASE 访问任意 PTE PTE(vaddr) (PMMPTE)(PTE_BASE (vaddr 12) * sizeof(MMPTE)) → 即 PTE_BASE[index] 对应虚拟地址为 index12 的页表项// ReactOS 中的自映射区域常量miarm.h#definePTE_BASE((PMMPTE)0xC0000000)// x86 页表自映射基址#definePDE_BASE((PMMPDE)0xC0300000)// x86 页目录自映射基址// 宏虚拟地址 → PTE 地址#defineMiAddressToPte(Va)\((PMMPTE)(((ULONG_PTR)(Va)12)*sizeof(MMPTE)(ULONG_PTR)PTE_BASE))// 宏验证地址是否在页表区域#defineMI_IS_PAGE_TABLE_ADDRESS(Address)\(((PVOID)(Address)(PVOID)PTE_BASE)((PVOID)(Address)(PVOID)PTE_TOP))amd64 下通过 PML4 自映射实现类似效果PML4E[511]指向 PML4 自身。9. 关键技术总结页表自映射x86/x64 利用顶级页表的一个自引用条目使页表本身在虚拟地址空间中可寻址操作系统无需在多个页表间切换即可修改任意 PTE。TLB 刷新策略切换进程时写入 CR3或 C111—ASID全局页面PTE_GLOBAL不受 TLB 刷新的影响通常映射内核页面。NX 位PAE 模式引入了 NX 位位63用于标记不可执行的内存页。x86-64 长模式强制使用 NX 位这是硬件 DEP数据执行保护的基础。大页面PDE.PS1 时PDE 直接映射大页面4MB/2MB/1GB减少 TLB 缺失。ReactOS 通过largepag.c管理大页面分配。PDE/PTE 模板ReactOS 在初始化时预定义ValidKernelPte、DemandZeroPte等模板页面分配时直接复用避免重复计算硬件标志。软件位PTE 的位 9-11位 52-62 在 x64可供操作系统自由使用。ReactOS 使用位 10PTE_PROTOTYPE标记原型 PTE位 9 标记转换态 PTE 等。参考资料Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A: Chapter 4 “Paging”AMD64 Architecture Programmer’s Manual, Volume 2: Chapter 5 “Page Translation and Protection”ReactOS 源码sdk/include/ndk/*/mmtypes.h架构相关 PTE/PDE 结构ReactOS 源码ntoskrnl/mm/ARM3/miarm.hPTE 标志和软件位定义ReactOS 源码ntoskrnl/mm/i386/page.c/pagepae.cx86 页表操作实现ReactOS 源码ntoskrnl/mm/amd64/init.camd64 页表初始化

相关新闻