kernel: 5.10
arch: arm64
pmd_addr_end就是对addr作2M对齐,每次增加2M的地址空间,比如可以用于vmemmap_populate时以2M为步长来遍历一段虚拟地址空间
# include/linux/pgtable.h
/*
* When walking page tables, get the address of the next boundary,
* or the end address of the range if that comes earlier. Although no
* vma end wraps to 0, rounded up __boundary may wrap to 0 throughout.
*/
#define pgd_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
#ifndef p4d_addr_end
#define p4d_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + P4D_SIZE) & P4D_MASK; \
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
#endif
#ifndef pud_addr_end
#define pud_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
#endif
#ifndef pmd_addr_end
#define pmd_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
#endif
pmd_addr_end宏展开为:
unsigned long __boundary = (addr + 2M) & ~(2M-1); //2M对齐
(__boundary - 1 < (end) - 1)? __boundary: (end);
实际pmd_addr_end就是对addr作2M对齐,每次增加2M的地址空间,比如可以用于vmemmap_populate时以2M为步长来遍历一段虚拟地址空间
#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3)
#define PMD_MASK (~(PMD_SIZE-1))
#define PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
从上面宏定义可以看出PMD_SHIFT为21,表示虚拟地址中PMD的偏移,PMD_SIZE为2M,表示一个PMD页表项所能表示的虚拟地址范围