L04:现代虚拟内存系统(Modern Virtual Memory Systems)
MIT 6.5900 Fall 2024 · Daniel Sanchez 主题:地址翻译与保护、线性/层级页表、TLB、中断与异常、TLB 与 Cache 组织、现代用途
一、虚拟内存的演进与目标
演进脉络:多道程序需求 → 分段(基址/界限)→ 碎片问题 → 分页 → 程序放不下主存 → 按需分页。
现代虚拟内存系统提供"大的、私有的、统一的存储"假象:
- 保护与隐私:多用户各有私有地址空间 + 一个或多个共享地址空间;页表 ≡ 内存视图 ≡ 名字空间;
- 按需分页:能运行超过主存的程序,隐藏机器配置差异;
- 代价是每次访存都要地址翻译。
二、地址翻译与保护
每条指令与数据访问都需地址翻译与保护检查。好的虚拟内存设计须空间高效且快(约一个周期)。
- 虚拟地址 =
<虚拟页号 VPN, 偏移 offset>; - 物理地址 =
<物理页号 PPN, offset>; - 保护检查依据内核/用户模式、读/写权限,违例则产生异常。
三、页表
线性页表(Linear Page Table)
页表项(PTE)*含:页是否存在的位、内存常驻页的 **PPN**、磁盘页的 **DPN**、保护与使用状态位。OS 在活动用户进程切换时设置*页表基址寄存器。
线性页表的大小:32 位地址、4KB 页、4 字节 PTE →
- 更大页?→ 内部碎片(页内未全用)+ 更大缺页代价;
- 64 位地址空间?即使 1MB 页也需
个 8 字节 PTE(35 TB!)。救赎在于:地址空间稀疏使用 → 层级页表。
层级页表(Hierarchical Page Table)
把 VPN 拆成多级索引(如 10-bit L1 索引 + 10-bit L2 索引 + offset),按需只为用到的部分分配下级页表。不存在的页对应空 PTE。可支持多种页大小(某 L1 项直接指向大页)。
四、TLB(Translation Lookaside Buffer)
地址翻译很昂贵——层级页表中每次引用变成多次访存。解法:在 TLB 中缓存翻译。
- TLB 命中 ⇒ 单周期翻译;
- TLB 缺失 ⇒ 页表遍历(page table walk)回填。
TLB 项含:V/R/W/D 位、tag、PPN。
TLB 设计
- 是否保存进程信息?无进程 ID → 上下文切换须刷新;每项打进程 ID(ASID)→ 不刷新但更贵;
- 大小与相联度:通常 32–128 项、高相联;
- TLB 覆盖范围(TLB Reach):TLB 能同时映射的最大虚拟地址空间。例:64 项 × 4KB 页 = 256KB(若连续);
- 增大覆盖范围的办法:多级 TLB(如 Skylake:64 项 L1 数据 TLB、128 项 L1 指令 TLB、1.5K 项 L2 TLB)、多种页大小(x86-64:4KB / 2MB / 1GB)。
TLB 支持多页大小
- 统一 TLB:先按 4KB 算索引探测,缺失再按 2MB 重算索引探测;
- 或为每种页大小设独立 TLB(与统一 TLB 各有利弊)。
处理 TLB 缺失
- 软件(MIPS、Alpha):TLB 缺失触发异常,OS 遍历页表并重载 TLB,遍历用特权"未翻译"寻址模式;
- 硬件(SPARC v8、x86、PowerPC):MMU 遍历页表并重载 TLB;遍历中遇到缺失页则放弃并对原指令发缺页异常。
地址翻译全流程
虚拟地址 → TLB 查找(命中→保护检查→物理地址到 Cache);TLB 缺失 → 页表遍历(硬件或软件)→ 页在内存则更新 TLB,不在内存则缺页(OS 调页);保护检查失败 → 保护故障(SEGFAULT)。
五、中断与异常(Interrupts)
中断:请求处理器关注的事件,改变正常控制流。
中断的原因
- 异步(外部事件):I/O 设备服务请求、定时器到期、电源中断/硬件失效;
- 同步(内部事件,即异常):未定义操作码、特权指令、算术溢出、FPU 异常、未对齐访存、虚拟内存异常(缺页/TLB 缺失/保护违例)、陷阱(系统调用)。
异步中断的处理
I/O 设备拉起某条优先级中断请求线;处理器决定处理时:在指令
中断处理程序:启用中断前先保存 EPC 以支持嵌套中断(需指令把 EPC 移入 GPR、需屏蔽进一步中断直到 EPC 被保存);读状态寄存器判断中断原因;用特殊间接跳转 mret(返回异常)启用中断、恢复用户模式、恢复硬件状态。
同步中断(异常)
由特定指令引起,一般该指令不能完成、需在处理后重启(流水线下需撤销一条或多条部分执行指令的效果);而陷阱(系统调用)则视为已完成(特殊跳转 + 切到内核态)。
缺页处理程序:定位(或创建)缺失页、从磁盘调入并更新页表(等待期间 CPU 可跑别的作业);无空闲页则换出一页(伪 LRU);因传页耗时(毫秒级),缺页完全由 OS 软件处理,未翻译寻址模式对内核访问页表至关重要。
六、TLB 与 Cache 组织
CPU 中的地址翻译
软件处理程序需缺页/保护违例上的可重启异常;TLB 缺失需硬件或软件机制回填。应对 TLB 额外延迟的机制:放慢时钟、流水化 TLB 与 Cache 访问、虚地址 Cache、TLB/Cache 并行访问。
虚地址 Cache(Virtual-Address Cache)
把 Cache 放在 TLB 之前。
- 优点:命中时一步完成;
- 缺点:上下文切换须刷新(除非 tag 含 ASID);页共享带来别名(aliasing)问题。
别名:两个虚拟页映射同一物理页,虚地址 Cache 可能有同一物理数据的两份副本,对一份的写对另一份的读不可见。
通解:禁止别名在 Cache 中共存。直接映射的软件(OS)解法——共享页的各 VA 须在 Cache 索引位上一致,使所有访问同一 PA 的 VA 在直接映射 Cache 中冲突。
TLB 与 Cache 并行访问
若索引位
- 设 Cache 索引
+ 块内偏移 ,页内偏移位数 :当 时可行; 时不行(索引用到了 VPN 位)。
L1 大于页大小的问题
当 L1 > 页大小时,索引用到了会被翻译的位,VA1 与 VA2 可能都映射到同一 PA → 仍有别名。
虚索引物理 tag(VIPT)+ 相联组织:用虚索引并行查,待 PPN 已知后比较
用 L2 反别名
- 通常用统一 L2 同时支撑 L1 指令与数据 Cache,L2 包含二者;
- MIPS R10000 反别名:若 VA1、VA2 都映射 PA 且 VA1 已在 L1/L2(VA1≠VA2),当 VA2 解析到 PA 后在 L2 检测到冲突 → 从 L1 清除 VA1、载入 VA2 ⇒ 无别名;
- 物理寻址的 L2 也可用于在虚寻址 L1 中避免别名(L2 "包含" L1,存虚 tag)。
七、虚拟内存的现代用途
- 桌面/服务器/手机处理器:完整的按需分页虚拟内存——机器间可移植、多用户/多任务保护、共享小物理内存、简化某些 OS 功能;
- 向量超算与 GPU:有翻译与保护但无按需分页(让作业放进内存、避免抖动到磁盘、多为批处理、可重启向量指令难实现);
- 多数嵌入式处理器与 DSP:只提供物理寻址(负担不起虚拟内存的面积/速度/功耗,常无次级存储可换,程序为特定内存配置定制)。
小结
- 现代虚拟内存提供大/私有/统一存储的假象,靠页表 + TLB 在每次访存做地址翻译与保护;
- 层级页表利用地址空间稀疏性解决 64 位下页表过大的问题,TLB 缓存翻译并可经多级/多页大小扩展覆盖范围;
- 中断分异步(外部)与同步(异常/陷阱),用精确中断与 EPC 支持可重启;
- TLB 与 Cache 可并行访问(受索引位约束),虚地址 Cache 的别名问题可用 OS 约束或 L2 反别名解决。
下一讲:流水线(Pipelining)