我不了解 Linux,所以我会回答 Windows。一些内核空间是“全局的”,这是在 PTE 中设置的一个标志,表示它被多个进程使用。 INVPCID 指令可以在寄存器操作数中配置,以在 TLB 无效中包含或排除这些条目。这些页表条目在进程之间共享,并且都出现在每个进程的页表中的相同位置。这样,只需要更新单个 PTE,不需要同步其他进程的其他 PTE,因为它们都在物理地址上共享单个 PTE。
http://www.cs.miami.edu/home/burt/journal/NT/memory.html
一些内核内存对所有进程不可见,并且对每个进程都是私有的(不会改变它仍然是环 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 位,然后通过将其乘以 8(或 4)将现在位于虚拟地址末尾的 PT 中的偏移量弥补为 12 位(因此右移 12和左移 3(或 2 对于 32 位条目))。 1 环回带走 1 层间接,你得到 PTE 的虚拟地址。 2个环回将为您留下用于转换该特定虚拟地址的PDE的虚拟地址,依此类推。 32 位窗口上的 PTE_BASE 是偏移量 110000000 左移以形成 32 位,而 PDE_BASE 是偏移量 110000000110000000 左移以形成 32 位。它在宏中使用,具有此前缀的任何虚拟地址将根据定义分别成为 PTE 或 PDE 的一部分。 Windows 为页表层次结构选择偏移量 1100000000,但它可以是 2^9 组合中的任何一种。
KAISER 或 KPTI,旨在缓解崩溃,很可能每个流程有 2 个cr3s。在捕获到内核时,用户模式的受限 cr3 将包含单个内核 PML4E(足以访问执行交换的初步中断调度例程函数)将被包含所有内核 PML4E 的完整 cr3 替换。
windows上的物理内存见这里:https://superuser.com/a/1549970/933117