pmd_addr_end宏

博客内容主要探讨了Linux内核在arm64架构下,如何进行2M对齐的地址操作,特别是在pgd_addr_end、p4d_addr_end、pud_addr_end和pmd_addr_end等宏定义中的应用。这些宏用于在遍历虚拟地址空间时以2M为单位前进,例如在vmemmap_populate函数中的使用。PMD_SIZE表示一个页表项覆盖的2M虚拟地址范围,PMD_SHIFT为21,表明PMD在虚拟地址中的位置。这些概念和操作对于理解Linux内存管理和内核地址空间布局至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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页表项所能表示的虚拟地址范围

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值