计算机体系结构 20:Sv32、TLB 与权限
计算机体系结构 20:Sv32、TLB 与权限
核心问题
第 16 到第 19 篇把数据缓存看成“物理地址进入缓存后发生什么”。这一篇补上物理地址之前的一段:一个 load、store 或取指给出的地址通常先是虚拟地址,处理器要用页表把它翻译成物理地址,再把结果交给后续缓存层级。
本篇只回答一个问题:在 RISC-V Sv32 下,TLB miss、page fault 和 data cache miss 为什么是三件不同的事。
这三个词常被混在一起:
- TLB miss:地址翻译缓存没有现成条目,需要查页表。
- page fault:页表项或权限检查不允许这次访问,需要陷入软件处理。
- data cache miss:已经得到物理地址后,数据缓存里没有对应数据块。
一个有效翻译可以 TLB miss,但不 page fault。一次 TLB hit 也可以 data cache miss。反过来,page fault 发生时,数据访问还没有资格进入数据缓存模型。
这里的关键模式是先分清“名字缓存”和“数据缓存”。TLB 缓存的是虚拟页到物理页的翻译和权限信息;data cache 缓存的是物理地址对应的数据块。两个结构都叫 cache,但缓存对象不同,缺失含义也不同。
边界
本文使用 RISC-V Privileged Architecture 的 Sv32 规则作一手依据。2026-09-22 通过可读官方 supervisor 页面核对到 Supervisor-Level ISA 1.13;固定版本 URL 当前不可直接读取,因此正文引用可读官方 URL,不把固定版本 URL 当作本轮已访问证据。规范说明:Sv32 虚拟地址由 20 位 VPN 和 12 位页内偏移组成,经过两级页表把 VPN 翻译成 22 位 PPN,12 位页内偏移保持不变;satp 选择地址翻译模式并给出根页表 PPN;规范允许实现缓存地址翻译,但不规定 TLB 容量、替换策略或命中延迟。
本文的执行证据来自一个有限 Python 模型:
输出附件:
sv32_trace.json、sv32_model_stdout.json
从仓库根目录复跑:
1 | |
证据等级:功能执行。
它不是真实 RISC-V hart、不是 Linux 内核页故障记录、不是硬件 TLB 采样,也不是硬件数据缓存采样。模型只覆盖本文用到的 Sv32 小页、一个合法 4 MiB 大页、S/U 权限、SUM 的一部分行为、TLB 条目权限重查,以及一个微型 data cache。MXR、ASID、全局页、PMP、硬件 A/D 位更新和并发页表遍历竞态不在本文证据范围内。
Sv32 地址怎样拆开
取虚拟地址:
1 | |
Sv32 使用 4 KiB 页。低 12 位是页内偏移:
1 | |
模型设置根页表中 VPN[1]=1 的项指向二级页表 PPN 0x200。因为 PTE 大小是 4 字节,二级页表中 VPN[0]=1 的 PTE 地址为:
1 | |
这个叶子 PTE 的 PPN 是 0x300,权限是 R|W,并且 V/A/D 已置位。得到的物理地址是:
1 | |
输出里对应事件是:
1 | |
这里发生的是 TLB miss,不是 page fault。页表项有效,权限允许 S 模式 load,翻译能完成。
判断一次地址访问时,先问“页表是否允许”,再问“缓存是否命中”。不要把“需要查表”误判成“不能访问”。
TLB miss 后还能 data cache miss
同一次访问在翻译完成后才进入数据缓存。模型给同一条访问接了一个很小的 data cache:
1 | |
第二次访问同一虚拟地址时,TLB 先命中:
1 | |
然后同一物理 cache line 在 data cache 中命中:
1 | |
这四个事件说明了两个独立层次:
| 次数 | 翻译层 | 数据层 |
|---|---|---|
| 第一次 | TLB miss,页表遍历成功 | data cache miss |
| 第二次 | TLB hit | data cache hit |
这不意味着 TLB hit 总会带来 data cache hit。这里只是访问了同一个物理 cache line。换一个已翻译但从未进入 data cache 的物理地址,仍然可以出现 TLB hit + data cache miss。
权限在 TLB hit 时仍要成立
TLB 条目不能只缓存 PPN。它还必须带着足以判断权限的信息,或者命中后能用等价方式重新检查权限。否则会出现一种危险错误:S 模式先访问 supervisor-only 页,把条目装进 TLB;随后 U 模式访问同一 VA,如果实现只看 VPN 命中就直接返回 PA,U 模式就绕过了权限。
模型把这个错误显式堵住:TLB hit 时仍按当前 mode、access 与 SUM 检查权限。
输出里先有 S 模式 load 成功,再有 U 模式访问同一页失败:
1 | |
pte_address 写成 tlb_cached_pte,表示这不是页表遍历中发现的 PTE 地址,而是 TLB 已缓存条目在当前权限语境下不再允许这次访问。
SUM 只影响 S 模式 load/store 访问 U 页,不允许 S 模式从 U 页取指。模型中的 U 页案例给出三种结果:
| 访问 | 结果 |
|---|---|
S load U 页,SUM=0 |
page fault |
S load/store U 页,SUM=1 |
允许 |
| S fetch U 页 | page fault |
缓存结果不能缓存掉安全上下文。只要权限依赖当前模式、访问类型或状态位,命中路径也必须保留等价检查。
大页是另一种叶子位置
Sv32 不只有 4 KiB 页。level-1 PTE 如果已经是叶子,可以表示 4 MiB superpage,但 PPN 的低 10 位必须满足对齐要求。模型实现了一个有限合法路径:
1 | |
输出事件:
1 | |
随后访问同一个 4 MiB 范围内的 0x01802040,TLB 命中同一个 superpage 条目:
1 | |
这里不能把“模型没写大页”伪装成硬件 page fault。硬件规范允许合法大页;如果教学模型不支持,应该报告模型能力不足。当前版本选择实现这个有限合法路径,并只在 misaligned superpage 时返回故障。
本篇验收
- 能从
0x00401234手算VPN[1]、VPN[0]、offset、PTE 地址和最终 PA。 - 能解释 TLB miss、page fault、data cache miss 的不同含义。
- 能指出 TLB hit 仍需要权限检查,不能让 U 模式复用 S 模式 supervisor 页命中。
- 能说明
SUM对 S 模式访问 U 页的边界:load/store 与 fetch 不同。 - 能给出 4 MiB superpage 的对齐要求和本文的有限实现范围。
练习
练习 1
给定 VA=0x00401234,页表设置与本文相同。写出 VPN[1]、VPN[0]、offset、L0 PTE 地址和 PA。
答案:
1 | |
练习 2
如果 S 模式先 load 一个 supervisor-only 页并填入 TLB,随后 U 模式 load 同一 VA,能否直接使用 TLB 命中的 PPN?
答案:不能。TLB hit 只说明找到了翻译条目,不说明当前权限允许访问。命中路径仍要检查 PTE 的 U 位、当前 privilege mode 和访问类型。本文模型输出 user_to_supervisor_page,并把地址来源标为 tlb_cached_pte。






