据我所知,每个进程都可以有单独的页表,可以在上下文切换期间通过更新TTBR0 / 1_EL1来指向。每个进程的内部页表,一些条目将是特定于进程的(nG = 1),其他条目将指向公共资源(nG = 0)。
我搜索了堆栈溢出和其他网站,但无法获得有关全局页面维护的令人满意的解释。
提前致谢!
答案 0 :(得分:1)
- 如果页表条目(PTE)在一个进程的页表中被标记为全局,是否意味着PTE必须完全相同/指向所有其他页表中的完全相同的物理块?
醇>
如果PTE在某个页表(在内存中)中有nG = 0(设置为全局),则表示没有。但是当此PTE加载到TLB高速缓存中时,此位会更改TLB如何将此虚拟地址与此高速缓存的PTE进行匹配(在支持ASID的模式下;" 要解决此问题,ARMv8还会添加非全局(nG) )在页表描述符中标记,从而通过清除标志" - https://dl.acm.org/citation.cfm?id=3062267" ARM上的内核的指令级数据隔离"在特定页面上忽略ASID。 ):每个请求从当前ASID与用于nG = 1(进程)映射的PTE ASID匹配,并且将仅基于nG = 0(全局)映射的虚拟地址进行匹配。因此,在所有页表中保持全局映射相同是非常方便的。并且只将其用于全局内容,例如内核地址空间,而不需要频繁更改。
- 如果出现不一致会怎样?我的意思是,如果一个进程的nG = 0而另一个进程的nG = 1用于相同的虚拟>物理映射,是否从OS创建了错误的页表?
醇>
当内存中的PTE不正确时,没有任何反应。当它在TLB中缓存并且进程被切换时,将生成错误的物理地址以访问该虚拟地址(映射)。
操作系统如何确保每个全局PTE在不同进程中保持一致,以便所有进程都可以看到全局PTE的一次更新'页表?
当OS创建一些映射时,它会编辑相关的页表。因此,添加全局映射时,它会将其写入正确的位置。我认为(但不确定)可以在进程之间部分共享内核空间页表的一些子树(当架构将页表实现为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 ARM Cortex-A系列程序员指南ARMv8-A - 12.3。将虚拟地址转换为物理地址)。在不同进程中管理全局映射的另一种可能的解决方案是从操作系统内存描述符(Linux中的VMA)到其注册的所有页表的链接,并使用某种停止所有可以使用它的cpus / cores / processes进行更新,更改映射,在每个CPU核心上执行tlb flush for range,不要停止所有cpus / cores / processes。
据我了解,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_*
,{{ 1}}):
http://elixir.free-electrons.com/linux/v4.11/source/arch/arm64/include/asm/pgtable-prot.h#L67
PROT_KERNEL_*
Linux / Aarch64的文档仅说TTBR0 / TTBR1:https://www.kernel.org/doc/Documentation/arm64/memory.txt&#34; AArch64 Linux上的内存布局&#34;
当内核地址具有时,用户地址将位63:48设置为0 相同的位设置为1. TTBRx选择由第63位给出 虚拟地址。 swapper_pg_dir仅包含内核(全局) 用户pgd仅包含用户(非全局)映射时的映射。 swapper_pg_dir地址写入TTBR1并且从不写入 TTBR0。