arch/arm64/include/asm/pgtable-hwdef.h 中有如下定义
/*
* Size mapped by an entry at level n ( 0 <= n <= 3)
* We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
* in the final page. The maximum number of translation levels supported by
* the architecture is 4. Hence, starting at at level n, we have further
* ((4 - n) - 1) levels of translation excluding the offset within the page.
* So, the total number of bits mapped by an entry at level n is :
*
* ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
*
* Rearranging it a bit we get :
* (4 - n) * (PAGE_SHIFT - 3) + 3
*/
#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3)
该宏的注释翻译一下,大概的意思是:
在每一级“translation levels”中,也就是PGD, PUD, PMD 中,
都是使用 (PAGE_SHIFT - 3) 个bits作为map。且当前架构arm64 支持的最大的页表级数为4。
因此,除了PAGE_SHIFT,Ln 级索引(L0 索引即PGD, L1 索引即PUD,以此类推)的偏移还有
((4 - n) - 1) 个 (PAGE_SHIFT - 3) 。因此计算公式就是
((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
对照下图,L1-L3 索引所在的偏移量分别是
L3 索引所在的偏移量: PAGE_SHIFT = 12
L2 索引所在的偏移量:1 * (PAGE_SHIFT-3) + PAGE_SHIFT = 21
L1 索引所在的偏移量:2 * (PAGE_SHIFT-3) + PAGE_SHIFT = 30
L0 索引所在的偏移量:3 * (PAGE_SHIFT-3) + PAGE_SHIFT = 39
验证一下,Ln 索引对应的偏移为 ARM64_HW_PGTABLE_LEVEL_SHIFT(n),计算结果如下
/*
* PGDIR_SHIFT = ARM64_HW_PGTABLE_LEVEL_SHIFT(0) = 39
* PUD_SHIFT = ARM64_HW_PGTABLE_LEVEL_SHIFT(1) = 30
* PMD_SHIFT = ARM64_HW_PGTABLE_LEVEL_SHIFT(2) = 21
*/