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