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级页表:
- PGD:Page Global directory 全局页表
- PUD:Page Upper Directory 上层页表
- PMD:Page Middle Directory 中间页表
- 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 |
来源:oschina
链接:https://my.oschina.net/u/4375893/blog/4260744