【问题标题】:Writing the translation lookaside buffer写入翻译后备缓冲区
【发布时间】:2014-03-20 02:19:53
【问题描述】:

应用程序使用虚拟内存。这是一个不错的概念,我们可以将它视为一个连续的块,而不必关心它是否在物理 RAM 中是连续的,甚至是否在硬盘上。

据我所知,虚拟地址和物理地址之间的映射是由 CPU(或至少在硬件中)使用转换后备缓冲区直接完成的。

我假设内核以某种方式维护了 TLB 的内容,但在这里我有点卡住了,所以我有 3 个问题:

查询、读取和写入 TLB 内容的具体汇编指令是什么? 我在谷歌上搜索与此主题相关的操作码并不是很幸运。我刚刚找到了 INVLPG 和 TLBWI。因为我对这种深度不熟悉,所以也许我只是使用了错误的搜索词。如果您立即找到它,您会使用哪些搜索词?

所有这些汇编指令都需要特权 CPU 模式吗?

TLB的初始内容是什么?如果TLB一开始是空的,是否意味着操作系统的第一条汇编指令将直接映射到物理内存(这样虚拟地址 == 物理地址)?

【问题讨论】:

  • TLB(我认为)只是页表的缓存——一种驻留在指定所有映射的主物理内存中的结构。 TLB 仅在内核进行更改时才需要失效(我认为,再次)。
  • 不知道TLB的内容,但是x86机器都在real mode启动
  • @Linuxios:这可以解释为什么它被称为缓冲区。如果物理 RAM 中的实际页表从不交换,那也很容易理解。
  • @ArjunShankar:天哪!在 DOS 中摆弄这些东西 20 年后(不知道我实际上做了什么),我终于回来尝试在汇编程序级别上理解它......感谢您的评论 - 它提供了一个很棒的突触连接。
  • 检查wiki.osdev.org/Paging#Page_Table;这包含填写表格和打开分页的所有详细信息。基本上它只是一堆 32 位条目,其在物理内存中的基数由寄存器 cr3 设置。

标签: assembly x86 i386 tlb


【解决方案1】:

我想总结一下这个社区wiki帖子中的cmets,结合我目前的理解。 如果您开始从抽象的角度了解页表和翻译后备缓冲区,您可能需要阅读此内容。但是,这篇文章可能无法保证位和字节的 100% 正确。

启动电脑

i386 PC 在real mode 中启动。此模式仅使用物理内存,还不关心虚拟内存。所有指令都以高权限执行。我们可以认为这是处于内核模式。

操作系统(不管是 Linux 还是 Windows 都无所谓)在这种模式下执行。它将建立页表,然后将CPU切换到protected mode

; set PE bit
mov eax, cr0
or eax, 1
mov cr0, eax
; far jump (cs = selector of code segment)
jmp cs:@pm
@pm:
; Now we are in protected mode.

写页表的操作码

page table 驻留在物理内存中,永远不会被交换到磁盘。因为页表不在翻译后备缓冲区中,所以我们可以使用简单的内存写入指令如mov 来填充页表。不需要特定的汇编指令来设置页表。

翻译后备缓冲区

翻译后备缓冲区只是页表的缓存。为了不与“普通”缓存混淆,它位于 CPU 的不同部分。

如果操作系统写入页表(在 RAM 中,而不是在缓存中),每个 CPU 上至少需要有一条特定的汇编指令:用于清除 TLB 以便 CPU 重新读取内存中的页表。

清除完整的 TLB 可能会浪费性能,因为只能将单个页面交换到磁盘。因此,i486 汇编指令invlpg 只会使单个页面无效。

是否有特权 TLB 操作码?

清除 TLB 对应用程序来说似乎不是很重要。即使可以在用户模式下执行指令,CPU 也只会再次读取原始页表。但是,因为只有内核才能写入页表,所以清除 TLB 的汇编指令是高权限指令听起来不错。

TLB 的初始内容

最初的内容并不重要。操作系统会设置页表,然后

  • 清除 TLB
  • 将 CPU 切换到保护模式

【讨论】:

  • 实际上可以将页表本身交换到磁盘上。页面目录条目 (PDE) 可以标记为不存在,这允许它们指向的页表条目被换出。不过,我不知道有多少操作系统在实践中这样做。
【解决方案2】:

在第一次启动时,分页被禁用,所以线性地址 = 物理地址。

x86-64 UEFI 固件必须设置某种简单的页表,可能是身份映射物理内存,因此虚拟 = 物理(但 IDK,如果您在意,请查看规范),因为 x86-64 长模式需要分页已启用。

为了在旧版 BIOS 模式下启动,固件将 CPU 切换回实模式并在 MBR 引导加载程序运行之前安装旧版 BIOS int 10h 等处理程序。


在 x86 上,TLB 由硬件管理(页面遍历以响应 TLB 未命中,对软件不可见)。页表必须采用硬件知道如何直接读取的基数树数据结构(使用物理地址作为级别之间的指针)。 (https://wiki.osdev.org/Paging/https://wiki.osdev.org/Page_Tables)。

请参阅What happens after a L2 TLB miss? 了解更多关于硬件页面遍历本身获取数据并创建 TLB 条目以便加载或存储(或代码获取)可以完成的事实。

唯一的控制软件是 invlpg 来使一个 4k 页面的缓存信息无效(例如,在更改它的页表条目之后),因此 HW 将在下次访问时使用 page-walk 重新加载它。 (或者重新加载 CR3 会使除“全局”条目之外的所有内容都无效。还有 PCID(进程上下文 ID)硬件支持使用 ID 标记 TLB 条目,因此在同一物理核心上的几个不同页表之间频繁交换不必是性能灾难。)

你告诉 CPU 在哪里可以找到带有mov cr3, reg 的页表来设置顶级页目录的物理地址。 (还有一个控制寄存器位,用于控制是否启用分页;在保护模式下是可选的。)

另见How does x86 paging work?


相比之下,像 MIPS 这样的一些 ISA确实 使用 软件 TLB 管理,其中 TLB 未命中陷阱到操作系统提供的处理程序,有点像页面错误处理程序,它使用自己的数据结构(在不能 TLB-miss 的特殊内存区域中)。 TLBWI is a MIPS instruction,不是 x86。

这不是 x86 的选项。

【讨论】:

    猜你喜欢
    • 2012-02-18
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多