序言
我是一名操作系统爱好者,我的内核运行在 80486+ 上,并已支持虚拟内存。
从 80386 开始,英特尔和各种克隆处理器家族的 x86 处理器已经支持带分页的虚拟内存。众所周知,当 CR0
中的 PG
位被设置时,处理器使用虚拟地址转换。然后,CR3
寄存器指向顶层页目录,即将虚拟地址映射到物理地址的 2-4 级页表结构的根目录。
MOV
)CR3
与顶级页目录地址或任务切换来完成此操作。据我了解,虚拟内存系统始终在更改后重新加载 CR3 是完全有效的方法。这是浪费的,因为 TLB 现在会丢弃完全良好的条目,因此在 80486 处理器中引入了
INVLPG
指令。 INVLPG
将使与源操作数地址匹配的 TLB 条目无效化。
然而,从Pentium Pro开始,我们还有全局页,它们不会随着移动到CR3
或任务切换而被清除;而AMD x86-64 ISA称,某些上层页表结构可能会被缓存并且不能通过INVLPG
使其失效。为了对每个ISA需要和不需要什么有一个连贯的认识,人们实际上需要下载一个多达1000页的数据手册,以阅读其中的一些页面,即使那些文档似乎在TLB失效方面也特别模糊。
问题
为简单起见,可以假设我们正在谈论单处理器系统。此外,可以假设更改页面结构后不需要进行任务切换。(因此,INVLPG
始终至少应与重新加载CR3
寄存器一样好)。
基本假设是,在每次更改页面表和页面目录后都需要重新加载CR3
,这样的系统是正确的。但是,如果想要避免不必要地清除TLB,则需要回答以下2个问题:
假设ISA支持
INVLPG
,在进行了哪些更改后可以安全地使用它而不是重新加载CR3
?例如,“如果取消映射一个页面帧(将相应的表项设置为未出现),则始终可以使用INVLPG
”?在不触及
CR3
或执行INVLPG
的情况下,可以对表和目录进行哪些更改?例如,“如果根本没有映射页面(未出现),则可以写入一个具有Present=1
的PTE,而无需刷新TLB”?
即使阅读了大量ISA文档以及在Stack Overflow上与INVLPG
相关的所有内容,我个人仍然不确定我所提出的任何一个示例。事实上,一个notable post立即指出:“我不知道你应该在什么时候使用它,什么时候不应该使用它。”因此,您可以提供任何确定、正确的示例,最好是有文献支持的,适用于IA32或x86-64。