首页 > 解决方案 > 页面错误处理程序可以生成更多页面错误吗?

问题描述

当我们处于用户模式并发生页面错误时,我有点困惑。

IIRC,当 TLB 尝试将我的(用户空间)虚拟地址映射到物理地址并且失败时,将生成页面错误。

然后它会生成一个将由操作系统同步处理的异常。但现在的问题是:这个异常处理程序代码的地址及其相关数据很可能也不在 TLB 中!

这是递归的还是这个内存地址的内核范围受不同规则的约束(例如,虚拟/物理内存之间的自动映射以避免需要使用 TLB?)

谢谢!

标签: linuxoperating-systemcpu-architecturetlbpage-fault

解决方案


不,Linux 不会换出内核内存。 (出于这个和类似的原因,例如确保页面错误处理程序不会在任何访问内存的随机指令之前运行)。

对内核内存进行分页的操作系统肯定需要将页面错误处理程序、页表和磁盘 I/O 代码保存在内存中......


此异常处理程序代码及其相关数据也不会出现在 TLB 中!

您将页面遍历(TLB 未命中)与页面错误(虚拟页面的条目无效或权限不足,必要时在页面遍历之后进行)混为一谈。

在 x86 和大多数(?)其他 ISA 上,页面遍历是由硬件完成的。请参阅L2 TLB 未命中后会发生什么?.

操作系统为 CPU 提供顶级页表的物理mov cr3, rax地址(例如在 x86 上),CPU 透明地处理其他所有内容。(唯一的软件 TLB 管理是在修改内存中的页表条目后使可能缓存的条目失效。例如 x86 invlpg

硬件页表管理允许 CPU在数组上的循环接近页边界时推测性地执行 TLB 遍历,而不是等到实际负载触及下一页。并且页面遍历延迟被乱序执行部分隐藏,还有很多好东西。Skylake 甚至有 2 个 page-walk 单元,因此它可以并行处理 2 个 TLB 未命中(或者两者都可能是投机或需求)。


在具有软件页面遍历的 ISA 上,TLB 未命中处理程序与页面错误处理程序是分开的。

例如,在 MIPS 上,有一个特殊的地址范围,其映射方式与普通内核虚拟地址不同:

如果地址以0b100[top 3 bits] 开头,则转换为底部 512 MB 的物理内存并且不经过 TLB。(缓存和未映射)。称为kseg0。用于内核指令和数据。

MIPS TLB 处理 - https://people.csail.mit.edu/rinard/teaching/osnotes/h11.html

(设置了高位的 MIPS 地址只能由内核代码使用,用户空间访问错误。即,为 MIPS 内置了一个高半内核。)

这有点像将 512MiB 的低物理内存映射到硬件中。显然,内核希望将其页面查找数据结构保持在该范围内,但它可以使用它想要的任何数据结构,例如基于开始/长度。


推荐阅读