linux内核页表更新
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核页表更新相关的知识,希望对你有一定的参考价值。
在linux x86中分页。
- 每个进程都有自己的页面目录。
- 页表行走从CR3指向的页面目录开始。
- 每个进程共享内核页面目录内容
假设三个句子是正确的,让我们说一些进程进入内核模式并更新他的内核页面目录内容(地址映射,访问权限等......)
题。由于内核地址空间是在进程之间全局共享的,因此这个更新必须与其他进程的页面目录同步,对吧?
怎么管理这个?
先感谢您。
我不知道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 MiAddressToPe (x) ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + (ULONG_PTR)MmPteBase))
优雅地工作,以便将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。在64位上,可以强制限制PDPT不能被分页,但是在32位上,不能存在类似的限制,因为明确的是页面表可以被分页,这意味着必须在32位上进行同步。
KAISER,或KPTI,旨在减轻崩溃,为简单起见,32位类比,每个过程最有可能有2个cr3
s。在捕获到内核时,用户模式的受限制的cr3将被包含所有内核PDE的完整cr3替换。
当内核更改页表条目时,必须以原子方式进行这些更新:
在64位内核中,这可以使用64位内存操作方便地完成,而i386需要使用CMPXCHG8。
(Qazxswpoi)
以上是关于linux内核页表更新的主要内容,如果未能解决你的问题,请参考以下文章