慢慢欣赏arm64内核启动13 primary_entry之__create_page_tables代码第三部分

分析代码

1:
	ldr_l	x4, idmap_ptrs_per_pgd
	mov	x5, x3				// __pa(__idmap_text_start)
	adr_l	x6, __idmap_text_end		// __pa(__idmap_text_end)

	map_memory x0, x1, x3, x6, x7, x3, x4, x10, x11, x12, x13, x14

俄罗斯套娃 idmap_ptrs_per_pgd

第2行的含义是获取变量 idmap_ptrs_per_pgd 的物理地址,并物理地址里面的值加载到x4里面
ldr_l对应的宏定义如下

        /*
         * @dst: destination register (32 or 64 bit wide)
         * @sym: name of the symbol
         * @tmp: optional 64-bit scratch register to be used if <dst> is a
         *       32-bit wide register, in which case it cannot be used to hold
         *       the address
         */
        .macro  ldr_l, dst, sym, tmp=
        .ifb    \tmp
        adrp    \dst, \sym
        ldr     \dst, [\dst, :lo12:\sym]
        .else
        adrp    \tmp, \sym
        ldr     \dst, [\tmp, :lo12:\sym]
        .endif
        .endm

其中,“tmp=”没有参数传入,所以为空,走 .ifb 分支,ifb表示 if blank
而变量 idmap_ptrs_per_pgd 的定义如下

u64 idmap_ptrs_per_pgd = PTRS_PER_PGD;

PTRS_PER_PGD

而 PTRS_PER_PGD 的定义如下:

$ grep -rnw PTRS_PER_PGD arch/arm64/
arch/arm64/include/asm/pgtable-hwdef.h:72:#define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))

所以 PTRS_PER_PGD 依赖于 VA_BITS 和 PGDIR_SHIFT,而 VA_BITS 的值我们之前讨论过,为48, PGDIR_SHIFT 我们先看一下其定义

PGDIR_SHIFT

页目录偏移(PGDIR_SHIFT):这个宏定义了页目录级别(Page Directory Level)的页大小的对数。在ARM64架构中,页表结构可能包括多级,如页全局目录(PGD)、页上级目录(PUD)、页中间目录(PMD)和页表项(PTE)。PGDIR_SHIFT指定了从物理地址中提取页全局目录索引所需的位数。我们继续寻找其值 PGDIR_SHIFT 为多少

$ grep -rnw PGDIR_SHIFT arch/arm64/
arch/arm64/include/asm/pgtable-hwdef.h:69:#define PGDIR_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS)

PGDIR_SHIFT 又扯出两个宏定义,分别是 CONFIG_PGTABLE_LEVELS 和 ARM64_HW_PGTABLE_LEVEL_SHIFT

CONFIG_PGTABLE_LEVELS

其中,CONFIG_PGTABLE_LEVELS 的值如下:

$ cat .config | grep CONFIG_PGTABLE_LEVELS
CONFIG_PGTABLE_LEVELS=4

所以 ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS) 的值为 ARM64_HW_PGTABLE_LEVEL_SHIFT(0)

ARM64_HW_PGTABLE_LEVEL_SHIFT

而 ARM64_HW_PGTABLE_LEVEL_SHIFT 的值如下

$ grep -rnw ARM64_HW_PGTABLE_LEVEL_SHIFT arch/arm64/
arch/arm64/include/asm/pgtable-hwdef.h:41:#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)

而我们前面算过,n的值为0,所以宏定义为 ((PAGE_SHIFT - 3) * (4 - (0)) + 3) == ((PAGE_SHIFT - 3) * 4 + 3)

PAGE_SHIFT


PAGE_SHIFT 的宏定义如下:

$ grep -rnw PAGE_SHIFT arch/arm64/
arch/arm64/include/asm/page-def.h:14:#define PAGE_SHIFT		CONFIG_ARM64_PAGE_SHIFT

CONFIG_ARM64_PAGE_SHIFT

见到 CONFIG_ARM64_PAGE_SHIFT 应该就是终点,不太可能再俄罗斯套娃了

$ cat .config | grep CONFIG_ARM64_PAGE_SHIFT
CONFIG_ARM64_PAGE_SHIFT=12

最后的小套娃

所以最终 PGDIR_SHIFT 的值为 ((PAGE_SHIFT - 3) * 4 + 3) == 39
这就是 L0 索引的偏移
PTRS_PER_PGD 的值为 1 << (48 - 39) == 512,正如宏定义的名字描述,页全局目录共有512个表项。

准备建立恒等映射

第3行和第4行表示 x5和x6分别存储 __idmap_text_start 和 __idmap_text_end 的物理地址,也就是恒等映射区域的起始和结束物理地址。

adr_l 不是标准的arm64指令或者伪指令,在linux kernel的定义如下

        /*
         * @dst: destination register (64 bit wide)
         * @sym: name of the symbol
         */
        .macro  adr_l, dst, sym
        adrp    \dst, \sym
        add     \dst, \dst, :lo12:\sym
        .endm

其实就是把一个值的物理地址存放在某个寄存器中。

第6行表示开始建立恒等映射的列表,后面会有3章详细讲解其内容

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值