init_pg_dir 的大小及作用

博客主要探讨了init_pg_dir的大小和作用。在vmlinux.lds.S中INIT_DIR_SIZE为0x5000,而在arch/arm64/include/asm/pgtable.h中PTRS_PER_PGD为512,二者大小不一致。init_pg_dir主要在head.S和mmu.c中使用,head.S做页表映射,mmu.c释放内存,它是内核的块映射页表。

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

init_pg_dir 的大小

vmlinux.lds.S 中

在vmlinux.lds.S 中,有

init_pg_dir = .;
. += INIT_DIR_SIZE;
init_pg_end = .;

/*include/asm/kernel-pgtable.h*/
#define EARLY_ENTRIES(vstart, vend, shift) \                                     
    ((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR)

#define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
#define EARLY_PUDS(vstart, vend) (0)
#define EARLY_PMDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT))

#define EARLY_PAGES(vstart, vend) ( 1           /* PGDIR page */                \
            + EARLY_PGDS((vstart), (vend))  /* each PGDIR needs a next level page table */  \
            + EARLY_PUDS((vstart), (vend))  /* each PUD needs a next level page table */    \
            + EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */

#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR + TEXT_OFFSET, _end))
假设 vstart= 0xffff800010000000, vend= 0xffff80001210a000
EARLY_PGDS = ((0xffff80001210a000 - 1) >> 39)  -  (0xffff800010c94000 >> 39) + 1 + 1 = 2
EARLY_PUDS = 0
EARLY_PMDS = ((0xffff80001210a000 - 1) >> 30)  -  (0xffff800010c94000 >> 30) + 1 + 1 = 2

INIT_DIR_SIZE = 0x1000 * (1 + 2 + 0 + 2) = 0x5000 # 和System.map 中的一样

从System.map 中可以看到

127291 ffff800012105000 B init_pg_dir                                                                                                                                                                           
127292 ffff80001210a000 B _end                                                          
127293 ffff80001210a000 B init_pg_end 

INIT_DIR_SIZE = 0x5000 = 20480

pgtable.h 中

在 arch/arm64/include/asm/pgtable.h 中

extern pgd_t init_pg_dir[PTRS_PER_PGD];

#define PTRS_PER_PGD        (1 << (MAX_USER_VA_BITS - PGDIR_SHIFT)) /* MAX_USER_VA_BITS = 48 */
#define PGDIR_SHIFT     ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS) /* CONFIG_PGTABLE_LEVELS = 4,为页表级数*/

其中,ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS) 得到的是PGD, L0页表索引在64bit 虚拟地址所处的偏移量,即39。详见这里
图一

PTRS_PER_PGD = (1 << (MAX_USER_VA_BITS - PGDIR_SHIFT))
    = pow (2, 48-39)
    = 512

因此 PTRS_PER_PGD 为512,表示PGD 页表中页表项的个数。

至此可以看到在 arch/arm64/include/asm/pgtable.h 中 PTRS_PER_PGD = 0x200 的大小与lds 中的 INIT_DIR_SIZE=0x5000 并不一致。这里值得留意

init_pg_dir 的作用

init_pg_dir 貌似只在head.S 和mmu.c 中有使用。
head.S 做了一些页表映射的工作,mmu.c 中只有对这块内存的释放。
init_pg_dir 是对内核的块映射页表,详见这个页面:
https://blog.csdn.net/weixin_43512663/article/details/129908114

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值