memory-management - 在ARMv8中,如果全局页表项在不同进程之间发生冲突会发生什么?

标签 memory-management operating-system arm virtual-memory page-tables

我知道每个进程都可以有单独的页表,并且可以通过更新 TTBR0/1_EL1 在上下文切换期间指向。在每个进程的页表内,一些条目将是特定于进程的(nG=1),而其他条目将指向公共(public)资源(nG=0)。

  1. 如果页表条目 (PTE) 在一个进程的页表中被标记为全局,是否意味着该 PTE 必须与所有其他页表中完全相同/指向完全相同的物理 block ?
  2. 如果是,如果不一致会怎样?我的意思是,如果一个进程的 nG = 0 而另一个进程的 nG = 1 对于相同的虚拟->物理映射,这是否是操作系统创建的页表错误?
  3. 如果我的第二个问题相关,那么操作系统如何确保每个全局 PTE 在不同进程之间保持一致,以便所有进程的页表都能看到全局 PTE 的一次更新?

我在 stack-overflow 和其他网站上进行了搜索,但没有得到关于全局页面维护的令人满意的解释。

提前致谢!

最佳答案

  1. If a page table entry (PTE) is marked as global in one process's page-table, does it mean that the PTE has to be exactly same / pointing to exact same physical block in all other page-tables?

如果 PTE 在某些页表(内存中)中具有 nG=0(设置为全局),则没有任何意义。但是,当将此 PTE 加载到 TLB 缓存中时,该位会更改 TLB 将此虚拟地址与此缓存的 PTE 进行匹配的方式(在支持 ASID 的模式下;“为了解决此问题,ARMv8 还在页表描述符,因此通过清除标志来忽略特定页面上的 ASID"- https://dl.acm.org/citation.cfm?id=3062267 "ARM 上内核的指令级数据隔离"):每个请求都从当前 ASID 到 PTE ASID 进行匹配对于 nG=1(进程)映射,并且仅根据 nG=0(全局)映射的虚拟地址进行匹配。因此,在所有页表中保持全局映射相同是非常方便的。并且仅将它们用于全局事物,例如内核地址空间,而无需频繁更改。

  1. What happens in case of an inconsistency? I mean, if one process has nG = 0 and another has nG = 1 for same virtual->physical mapping, is that a faulty page-table creation from OS?

当内存中存在不正确的 PTE 时,什么也不会发生。当缓存在TLB中并且进程切换时,会生成错误的物理地址来访问该虚拟地址(映射)。

how does OS make sure that every global PTE is coherent across different processes, so that one update on Global PTE is seen by all processes' page-tables?

当操作系统创建一些映射时,它会编辑相关的页表。因此,当添加全局映射时,它会将其写入正确的位置。我认为(但不确定)可以在进程之间部分共享内核空间页表的一些子树(当体系结构将页表实现为像 x86 中的分层树时)。经常存在内核空间-用户空间分割(历史上2GB/2GB虚拟地址空间https://lkml.org/lkml/2006/1/10/189),一半的虚拟内存被映射给内核(全局)。在 ARM 上,这种分割通常是静态的,使用 EL1 的 TTBR0 作为用户空间页表根,使用 TTBR1 作为内核空间页表根(http://infocenter.arm.com/help/topic/com.arm.doc.den0024a/BABBEFAE.html 以及用于查找分割点的转换控制寄存器 TCR_EL1)。对于 L2/L3 页表,ARM 在页表中也会有子树,因此不同进程的一些 L2 记录可能会指向相同的 L3 页表以用于部分内核/全局映射(请参见图 12.8 64KB 页的虚拟到物理地址转换)位于 http://infocenter.arm.com/help/topic/com.arm.doc.den0024a/ch12s03.html 适用于 ARMv8-A 的 ARM Cortex-A 系列程序员指南 - 12.3. 将虚拟地址转换为物理地址。管理不同进程中的全局映射的另一种可能的解决方案是从操作系统内存描述符(Linux 中的 VMA)到其注册的所有页表的链接,并通过某种方式停止可以使用它的所有 cpu/核心/进程来进行更新,更改映射,对每个 CPU 核心上的范围执行 tlb 刷新,取消停止所有 cpu/核心/进程。

据我了解,ARM64 的 Linux 内核 4.11 知道 NG 位为 PTE_NG arch/arm64/include/asm/pgtable-hwdef.h :

 #define PTE_NG         (_AT(pteval_t, 1) << 11)    /* nG */

但是just uses it对于用户空间,将其设置为 nG=1(进程);对于内核空间,将其设置为 nG=0(全局)(PROT_DEVICE_*PROT_NORMAL_* PROT_KERNEL_*): http://elixir.free-electrons.com/linux/v4.11/source/arch/arm64/include/asm/pgtable-prot.h#L67

#define PAGE_KERNEL     __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
#define PAGE_KERNEL_RO      __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
#define PAGE_KERNEL_ROX     __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
#define PAGE_KERNEL_EXEC    __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
#define PAGE_KERNEL_EXEC_CONT   __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT)
...
#define PAGE_NONE       __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_PXN | PTE_UXN)
#define PAGE_SHARED     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
#define PAGE_SHARED_EXEC    __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
#define PAGE_COPY       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
#define PAGE_COPY_EXEC      __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
#define PAGE_READONLY       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
#define PAGE_READONLY_EXEC  __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
#define PAGE_EXECONLY       __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN)

Linux/Aarch64 的文档仅介绍了 TTBR0/TTBR1:https://www.kernel.org/doc/Documentation/arm64/memory.txt “AArch64 Linux 上的内存布局”

User addresses have bits 63:48 set to 0 while the kernel addresses have the same bits set to 1. TTBRx selection is given by bit 63 of the virtual address. The swapper_pg_dir contains only kernel (global) mappings while the user pgd contains only user (non-global) mappings. The swapper_pg_dir address is written to TTBR1 and never written to TTBR0.

关于memory-management - 在ARMv8中,如果全局页表项在不同进程之间发生冲突会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44739789/

相关文章:

linux - 编译源代码并作为 cron 作业运行

c - ARM 处理器中的数据存储方式

c++ - arm-none-eabi-g++ 无法使用 -flto 正确处理弱别名

arm - 禁用 ARM 16 位拇指指令

java - 尝试在我的网络爬虫中运行几天时出现许多内存错误

c++ - 代码中的编程/内存/逻辑问题

php - PHP copy()如何处理内存

c++ - 通过池分配器中的内存地址访问空闲列表节点

c - 如何知道Linux中进程的分配方式?

operating-system - Prolog中识别操作系统