3. TLB缺失处理流程:硬件页表遍历 vs 软件填充
TLB缺失了怎么办?说白了,就是CPU在TLB里没找到虚拟地址到物理地址的映射关系。这时候处理器必须去查页表。怎么查?RISC-V给了你两条路:硬件帮你查,或者软件自己查。我当年刚接触RISC-V时,觉得这俩差不多,后来踩了坑才明白——选错了路,性能差好几倍。
3.1 硬件页表遍历(HW Walker)
硬件页表遍历,就是CPU内部集成一个状态机,TLB miss后自动去内存里遍历多级页表,把结果填回TLB。整个过程对软件透明。
- 硬件自动完成,无需软件干预
- TLB miss延迟固定,通常几十个cycle
- 实现复杂,占用芯片面积和功耗
我在一个高性能核项目中,HW Walker占了约5%的核面积。当时觉得肉疼,但实测下来,TLB miss延迟从软件方案的几百cycle降到了30-50cycle,值了。
3.2 软件填充(Software Refill)
软件填充走的是另一条路:TLB miss后触发异常,跳转到异常处理程序,由软件查页表、写TLB。RISC-V的SFENCE.VMA指令就是用来管理这个过程的。
- 低功耗嵌入式设计,面积敏感
- 页表结构灵活,支持自定义
- TLB miss频率低的应用
我曾经在一个IoT芯片上用过软件填充。面积省了,但每次TLB miss要跑几百行汇编代码。嗯,这里要注意——中断响应时间会变长,实时性要求高的场景要慎重。
3.3 RISC-V的SFENCE.VMA指令
SFENCE.VMA是RISC-V里用来同步页表修改的指令。说白了,就是告诉硬件:“我改了页表,你该刷TLB了。”
| 指令格式 | 功能描述 |
|---|---|
SFENCE.VMA |
刷整个TLB |
SFENCE.VMA rs1 |
刷指定地址的TLB项 |
SFENCE.VMA rs1, rs2 |
刷指定地址+ASID的TLB项 |
我曾经在一个多核系统里忘了加SFENCE.VMA,结果一个核改了页表,另一个核还在用旧TLB项。查了两天bug,最后发现是TLB没刷。记住:改页表后一定要刷TLB,多核下还要用FENCE保证顺序。
3.4 TLB缺失延迟分析
TLB miss的延迟,直接影响访存性能。我习惯把延迟拆成三部分来看:
- 检测延迟:TLB miss判断,通常1-2个cycle
- 填充延迟:查页表+写TLB,硬件方案30-50cycle,软件方案几百cycle
- 恢复延迟:重新执行访存指令,1-2个cycle
你想想看,如果程序频繁TLB miss,光填充延迟就能吃掉20%以上的性能。所以优化TLB命中率,比优化TLB填充速度更重要。
- HW Walker:TLB miss延迟平均35cycle
- Software Refill:TLB miss延迟平均280cycle
- TLB命中率每提升1%,整体性能提升约0.5%
我个人习惯在芯片设计初期就做TLB miss的延迟预算。如果目标频率1GHz,一个TLB miss吃掉35ns,那就要算清楚——你的应用能承受多少TLB miss?
如果做高性能计算,用HW Walker。如果做低功耗IoT,用Software Refill。但不管选哪个,都要在仿真阶段把TLB miss的延迟模型搭好。我习惯用SystemVerilog的assertion来监控TLB miss次数,超过阈值就报warning——这样流片前就能发现问题。