内存管理(二):页表映射过程

ε祈祈猫儿з 提交于 2020-05-01 14:29:34

Linux源码版本:4.14.75
我们知道在Linux中,操作的都是虚拟地址(有MMU的情况下),那么Linux是如何从虚拟地址找到物理地址的呢?
通过内存管理(一):虚拟地址空间布局我们知道,arm64支持64位地址宽度,但64bit并不是都用到了,linux最大支持的虚拟地址宽度为48bit,我们以39bit地址宽度为例
在这里插入图片描述
1、[63:39]指示页表的基地址寄存器,如果全为1,表示这个地址是内核空间地址,页表基地址寄存器是TTBR1_EL1;如果全为0,表示这个地址是用户空间地址,页表基地址寄存器是TTBR0_EL1
2、TTBR寄存器保存了第0级页表寄存器,0级页表寄存器有512个页表项,每个页表项8个字节,大小是4K,正好一页大小。通过虚拟地址的[38:30]作为索引查找相应的表项,表项中存储有下一级页表的基地址,0级页表每个页表项可以映射1G大小。
3、1级页表同样512个页表项,大小4K。通过虚拟地址的[29:21]作为索引查找相应的表项,表项中存储有下一级页表的基地址,1级页表每个页表项可以映射2M大小
4、2级页表512个页表项,大小4K。2级页表每个页表项映射一页4K大小,通过虚拟地址的[20:12]作为索引查找相应的表项,表项中存储了最终物理地址的[38:12],与虚拟地址的[11:0]组合之后就找到了最终的物理地址。






在这里插入图片描述
ARM64最大支持4级页表:

  1. PGD:Page Global directory 全局页表
  2. PUD:Page Upper Directory 上层页表
  3. PMD:Page Middle Directory 中间页表
  4. PT: Page table 页表
    下面是有关4级页表常用的一些定义
1.	[arch/arm64/include/asm/pgtable-hwdef.h]  
2.	   
3.	#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3)  
4.	   
5.	#define PTRS_PER_PTE        (1 << (PAGE_SHIFT - 3))  
6.	/* 
7.	 * PMD_SHIFT determines the size a level 2 page table entry can map. 
8.	 */  
9.	#if CONFIG_PGTABLE_LEVELS > 2  
10.	#define PMD_SHIFT       ARM64_HW_PGTABLE_LEVEL_SHIFT(2)  
11.	#define PMD_SIZE        (_AC(1, UL) << PMD_SHIFT)  
12.	#define PMD_MASK        (~(PMD_SIZE-1))  
13.	#define PTRS_PER_PMD        PTRS_PER_PTE  
14.	#endif  
15.	   
16.	/* 
17.	 * PUD_SHIFT determines the size a level 1 page table entry can map. 
18.	 */  
19.	#if CONFIG_PGTABLE_LEVELS > 3  
20.	#define PUD_SHIFT       ARM64_HW_PGTABLE_LEVEL_SHIFT(1)  
21.	#define PUD_SIZE        (_AC(1, UL) << PUD_SHIFT)  
22.	#define PUD_MASK        (~(PUD_SIZE-1))  
23.	#define PTRS_PER_PUD        PTRS_PER_PTE  
24.	#endif  
25.	   
26.	/* 
27.	 * PGDIR_SHIFT determines the size a top-level page table entry can map 
28.	 * (depending on the configuration, this level can be 0, 1 or 2). 
29.	 */  
30.	#define PGDIR_SHIFT     ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS)  
31.	#define PGDIR_SIZE      (_AC(1, UL) << PGDIR_SHIFT)  
32.	#define PGDIR_MASK      (~(PGDIR_SIZE-1))  
33.	#define PTRS_PER_PGD        (1 << (VA_BITS - PGDIR_SHIFT)) 

上面的数据表示的4级页表对应的偏移以及一个页表项所能覆盖内存范围大小。其中只有在页表层数大于3时,PUD页表才存在,只有在页表层数大于2时,PMU才存在。也就是说,
对于4级页表(如虚拟地址宽度48bit,页大小为4K),页表转换过程就是PGD—>PUD—>PMD—>PTR
对于3级页表(如虚拟地址宽度39bit,页大小为4K),PUD页表不存在,页表转换过程是PGD—>PMD—>PTR
对于2级页表(如虚拟地址宽度36bit,页大小为16K),PUD和PMD不存在,页表转换过程是PDG—>PTR
XXX_SHIFT表示的是该页表对应的虚拟地址偏移,该值与PAGE_SHIFT有关系。
XXX_SIZE表示的是该页表的一个页表项覆盖的地址空间大小,实际上也就是左移上面的XXX_SHIFT的大小。
PTRS_PER_XXX表示该页表有多少页表项
对于39bit的情况






虚拟地址偏移 页表项覆盖大小 页表项个数
PGD 30 1G 512
PMD 21 2M 512
PT 12 4K 512
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!