1

为什么页面全局目录中的条目会偏移?如果有的话,偏移量的意义是什么?

页面全局目录

地址 条目 1 条目 2
0000000080036000: 0x0000000000000000 0x0000000000000000
... ... ...
0000000080036bf0: 0x0000000000000000 0x0000000000000000
0000000080036c00: 0x000000002000d401 0x0000000000000000
0000000080036c10: 0x0000000000000000 0x0000000000000000
... ... ...
0000000080036ff0: 0x0000000000000000 0x0000000000000000

为什么不在 0x80036000 的位置 0 开始条目?

RISC-V (sv39) 的 Linux 和 seL4 使用三级页表,该页表具有页全局目录 (PGD)、页中间目录 (PMD) 和页表条目 (PTE)。PTE 条目指向可执行数据。正是这样:http ://www.science.unitn.it/~fiorella/guidelinux/tlk/node34.html

每个表为 4096 字节或 0x1000。每个条目是 64 字节。每个表可以有 512 个条目 (0x200)。一些表——特别是 PGD 和 PMD 有偏移的条目。换句话说,条目不是从表中的位置 0 开始,而是在表中途甚至 3/4 处为 0。我试图理解为什么会这样。

问题是关于表格中的位置而不是位置的内容。这就是为什么从 0x80036c00 开始而不是 0x2000d401 的含义?我知道 0x2000d401 指向 PMD 中的一个条目,该条目指向 PTE 中的一个条目,最后指向可执行代码。

我可以毫无问题地在概念上遍历页表。我的问题是我已经在我的二进制文件中移动了有效负载并修改了页表以使用 4KB 而不是 2MB 页面。这适用于特殊情况,但不适用于一般情况,我试图了解原因。我怀疑基于我得到的 QEMU 输出的页表有问题。

4

1 回答 1

1

为什么页面全局目录中的条目会偏移?如果有的话,偏移量的意义是什么?

PGD​​ 中的条目不是偏移量,它们是指向另一个页表的指针。页表中的偏移量包含在虚拟地址中。

Linux 和 seL4 使用三级页表,该页表具有页全局目录 (PGD)、页中间目录 (PMD) 和页表条目 (PTE)。

据我所知,这是过时的信息。我对 seL4 一无所知,但 Linux 使用 4 级页表。这可能还取决于 x86-64 与 ARM 之类的架构。即便如此,我很确定 Linux 使用 4 个级别,而不管架构如何,并且根据架构的要求简单地丢弃了一些级别。

每个表为 4096 字节或 0x1000。每个条目是 64 字节。每个表可以有 512 个条目 (0x200)。一些表——特别是 PGD 和 PMD 有偏移的条目。换句话说,条目不是从表中的位置 0 开始,而是在表中途甚至 3/4 处为 0。我试图理解为什么会这样。

这一段给了我一个提示(也许我错了)你的问题是关于 x86-64 架构的。在 x86-64 上有 4 个级别的页表。分页部分由硬件实现,处理器的 MMU 将自动跨页表将虚拟地址转换为物理地址。它也部分由软件(操作系统)实现,因为操作系统将填充页表等。

页表的某些部分可能为零的原因有多种。我在想的可能是页表条目所代表的内存部分不在进程的地址空间中。这意味着用户模式进程可以访问此地址,但会触发页面错误,因此内核应该终止该进程。

此外,如果它是内核页表,则可能只有一部分虚拟地址空间当前未被内核使用,因此可以通过在不同条目中放置零来丢弃。有几个原因可以解释为什么页表的某些部分为零。

可以肯定的是,在将页表“提供”给用户模式进程之前用零填充页表总是一个好主意,因为否则可能会发生触及另一个进程的地址空间的访问,这将是一个安全威胁. 例如,如果您在用户模式进程的页表中有一个未清零的条目,那么您可能有一个访问该虚拟地址的进程。它可以设置当前位(它不会触发页面错误)并且可以转换到另一个进程的地址空间。这将是一个漏洞。

不要忘记页表也是内存保护,因为它们将一个进程与另一个进程隔离开来,因为页表不应转换为属于另一个进程的地址。他们还具有用户与主管位,允许将用户模式与内核隔离。

关于分页,x86-64 上的 4 级分页方案有 PML4、PGD、PDT 和 PT。虚拟地址如下所示(二进制):

  Index in PML4    Index in PGD   Index in PDT    Index in PT     Offset in physical frame (12 bits)
0b000000000        000000000      000000000       000000000       000000000000

这里我只表示 48 位,因为高 16 位未使用(除非启用了新处理器上存在的 5 级分页)。基本上,每 9 位是相应页表中的一个索引/偏移量。12 个最低有效位是物理帧中的偏移量。Linux 只是为其页表命名,因为它支持多种体系结构。Linux 上的名称是 PGD、PUD(Page Upper Directory)、PMD 和 PTE。

页表条目指向另一个页表,该页表将用作使用在虚拟地址中找到的偏移量进行转换的表。

希望这能消除任何误解!随意评论任何事情。

于 2021-12-28T19:06:01.887 回答