我不了解Linux,所以我会回答Windows。某些内核空间是“全局”的,这是 PTE 中设置的一个标志,表明它被多个进程使用。这INVPCID
可以在寄存器操作数中配置指令以在 TLB 无效中包含或排除这些条目。这些页表条目在进程之间共享,并且全部出现在每个进程的页表中的同一位置。这样,只需要更新单个 PTE,并且不需要同步其他进程的其他 PTE,因为它们都在物理地址共享单个 PTE。
http://www.cs.miami.edu/home/burt/journal/NT/memory.html http://www.cs.miami.edu/home/burt/journal/NT/memory.html
某些内核内存对于所有进程来说都是不可见的,并且是每个进程私有的(不会改变它仍然是ring 0的事实)。在 32 位 Windows 系统上,这将是 0xC0000000–0xC0200000,其中包含所有用户空间 PTE 和 PDE,其中 0xC0000000 是允许方程式的 PTE_BASE
#define MiGetPteAddress (x) ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + (ULONG_PTR)MmPteBase))
#define MiAddressToPte(x) MiGetPteAddress(x)
优雅地转换故障虚拟地址cr2
到 PTE 的地址。这是每个进程私有的,因为每个进程都有相同的基本 PTE 分配基地址;如果它对所有进程都可见,它将很快占用虚拟内存,因为每组页面都必须按顺序分配。它不需要对所有进程都可见,因为一个进程对另一个进程的页表条目不感兴趣。页面错误始终在当前进程的上下文中进行处理,并且 0xC0000000–0xC0200000 在每个进程上下文中表示不同的内容。
然而,用于分配内核 PTE(用于内核地址)的内核空间 0xC0200000–0xC0400000 将是全局的,并由所有进程共享,但其中代表 0xC0000000–0xC0200000 的部分除外,根据我的计算,该部分将是 0xC0300000–0xC0300800,这是PDE 的用户模式端为 PDE_BASE = 0xC0300000–0xC0300FFF。
然而,不可能将用户 PDE 和内核 PDE 部分分开,使得前者是私有的,后者是全局的(即使 0xC0300000–0xC0300800 私有(指向不同的物理地址)和 0xC0300000–0xC0300FFF 指向相同的物理地址)每个进程),因为整个 PDE 区域 (0xC0300000–0xC0300FFF) 将位于同一物理帧上,并构成由cr3
,以及cr3
对于每个进程来说都是不同的,这意味着整个 PDE 区域(所有 PDE)必须为每个进程私有(每个进程复制和安装)。如果内核页表页面(包含内核页表的页面)被调出并调入新的物理位置,则所有 PDE 都必须同步,因为所有进程在不同的 cr3 物理地址处都有副本,而不是相同的物理 PDE 。我不确定它是如何(有效)ATM 的,因此明智的做法是施加限制,不允许内核页表被调出并将它们放在非分页池中;这样内核 PDE 将在所有 CR3 页面上保持不变。在 64 位上,可能会施加限制,即内核 PDPT 无法调出。在 32 位 Windows 上,进程以物理 CR3 页面启动,其 PDE 位于偏移量 1100000000(base 2)*4 字节,指向其本身,该页面是硬写入的,可能是通过短暂关闭 cr0 中的分页(因为写入不会)在没有需要写入的递归条目的情况下成功,从而产生悖论)。请注意,PD 条目本身是涵盖范围 0xC0000000–0xC0400000 的页表,即它指向 1023 个页表和 1 个页目录(本身)(2^10 个条目),因此允许通过其虚拟地址修改 PTE 。 CR3页面位于0xC0300000的原因是因为该地址具有相同的页目录和页表索引1100000000和1100000000,因此它自身循环两次,因此产生CR3页面,您可以通过地址修改PDE(还有其他像这样的特殊地址,例如 0xE0380000)。设置完成后,将进行适当的内核映射。在 64 位 Windows 上,这与使用指向自身的单个 PML4 表页设置进程类似,这样,由于环回量可变,可以填充和访问任何 PML4E、PDPTE、PDE 或 PTE。在 64 位 Windows 上,当进程终止时,进程的所有物理页都会移至空闲列表,其中包括所有用户物理 PDPT 页、PD 页、PT 页和 PML4/CR3 页。内核不会被标记为空闲列表。
一般来说,如果您知道 PML4 中的哪个条目是物理 PML4 页的递归条目,则可以计算出服务(用于转换)特定虚拟地址范围和特定虚拟地址的 PTE 结构的虚拟地址在那个范围内。您将 PML4 中的偏移量(32 位为 10 位;64 位为 9 位)附加到其自身的条目,附加到您要查找其服务 PTE 虚拟地址的虚拟地址的开头(这就是添加 0xC0000000在前面的 32 位方程中)并删除最后 12 位,然后将虚拟地址末尾的 PT 中的偏移量乘以 8(或 4),将其弥补为 12 位(因此右移 12左移 3 位(对于 32 位条目左移 2 位)。 1 个环回消除了 1 层间接,您将获得 PTE 的虚拟地址。 2 个环回将为您留下用于转换该特定虚拟地址等的 PDE 的虚拟地址。 32 位窗口上的 PTE_BASE 是左移 110000000 的偏移量,以形成 32 位,PDE_BASE 是左移 32 位的偏移量 110000000110000000。它用在宏中,并且根据定义,具有此前缀的任何虚拟地址将分别成为 PTE 或 PDE 的一部分。 Windows 为页表层次结构选择偏移量 1100000000,但它可以是 2^9 组合中的任何一种。
KAISER,或 KPTI,旨在缓解崩溃,最有可能有 2cr3
每个进程的 s。捕获到内核后,用户模式的受限 cr3 将包含单个内核 PML4E(足以访问执行交换的初步中断调度例程函数)将被包含所有内核 PML4E 的完整 cr3 替换。
至于windows上的物理内存,请看这里:https://superuser.com/a/1549970/933117 https://superuser.com/a/1549970/933117