慢慢欣赏arm64内核启动16 primary_entry之__create_page_tables代码第四部分populate_entries

要分析的代码

/*
 * Macro to populate page table entries, these entries can be pointers to the next level
 * or last level entries pointing to physical memory.
 *
 *	tbl:	page table address
 *	rtbl:	pointer to page table or physical memory
 *	index:	start index to write
 *	eindex:	end index to write - [index, eindex] written to
 *	flags:	flags for pagetable entry to or in
 *	inc:	increment to rtbl between each entry
 *	tmp1:	temporary variable
 *
 * Preserves:	tbl, eindex, flags, inc
 * Corrupts:	index, tmp1
 * Returns:	rtbl
 */
	.macro populate_entries, tbl, rtbl, index, eindex, flags, inc, tmp1
.Lpe\@:	phys_to_pte \tmp1, \rtbl
	orr	\tmp1, \tmp1, \flags	// tmp1 = table entry
	str	\tmp1, [\tbl, \index, lsl #3]
	add	\rtbl, \rtbl, \inc	// rtbl = pa next level
	add	\index, \index, #1
	cmp	\index, \eindex
	b.ls	.Lpe\@
	.endm

注释解义

这个宏定义我们按照老规矩,先读注释
第1行到第16行时注释,大概意思是填充页表项,当前页表的每个页表项的内容是下一级页表的物理地址,所以牵扯到本级页表和下级页表。这里牵扯到2个问题。

第一个问题:向哪里填充?这个由上一个宏定义 compute_indices 计算出来 istart 和 iend
也就是说,本级页表的基地址为 tbl,在 tbl 的 [istart, iend] 这个区间填充页表项

第二个问题:填充什么内容?填充下一级页表项的地址 + 页表属性

基于如上的原则,我们看看各个参数的含义

第一个参数 tbl,入参,本级页表的起始物理地址

第二个参数 rtbl,入参,下一级页表的起始物理地址

第三个参数 index,入参,起始索引,由上一个宏定义 compute_indices 给出

第四个参数 eindex,入参,结束索引,上一个宏定义 compute_indices 给出

第五个参数 flags,入参,该级页表项的属性
对于全局页表目录等非最后一级页表来说,其页表项填充的值为 PMD_TYPE_TABLE

$ grep -rn PMD_TYPE_TABLE ./arch/arm64/
./arch/arm64/include/asm/pgtable-hwdef.h:109:#define PMD_TYPE_TABLE		(_AT(pmdval_t, 3) << 0)

对于 _AT 来说,它是一个类型转换宏,用于显式地将一个值转换为指定的类型,以避免隐式类型转换可能带来的问题。在这个上下文中,它将数字 3 转换为 pmdval_t 类型。
这个值(即3)在页表操作中用于指示PMD条目指向下一级页表。
对于最后一级的页表来说,其值是在 __create_page_tables 前面的语句赋值
 
第六个参数 inc,入参,步长的意思,也就是相邻的页表项的值相差多少
对于全局页表目录等非最后一级页表来说,其页表项填充的值为 PAGE_SIZE,也就是说两两相差一个页表
对于最后一级的页表来说,其值是 SWAPPER_BLOCK_SIZE,其定义如下

/* Initial memory map size */
#if ARM64_SWAPPER_USES_SECTION_MAPS
#define SWAPPER_BLOCK_SHIFT     SECTION_SHIFT
#define SWAPPER_BLOCK_SIZE      SECTION_SIZE
#define SWAPPER_TABLE_SHIFT     PUD_SHIFT
#else
#define SWAPPER_BLOCK_SHIFT     PAGE_SHIFT
#define SWAPPER_BLOCK_SIZE      PAGE_SIZE
#define SWAPPER_TABLE_SHIFT     PMD_SHIFT
#endif

而 ARM64_SWAPPER_USES_SECTION_MAPS 在前面的章节分析为1,所以继续分析 SECTION_SIZE

$ grep -rnw SECTION_SIZE ./arch/arm64/
./arch/arm64/include/asm/pgtable-hwdef.h:78:#define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT)

SECTION_SHIFT 的定义如下

$ grep -rnw SECTION_SHIFT ./arch/arm64/
./arch/arm64/include/asm/pgtable-hwdef.h:77:#define SECTION_SHIFT		PMD_SHIFT

PMD_SHIFT 的定义如下

$ grep -rnw PMD_SHIFT ./arch/arm64/
./arch/arm64/include/asm/pgtable-hwdef.h:49:#define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)

ARM64_HW_PGTABLE_LEVEL_SHIFT 在前面的章节分析过

#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3) == (12 - 3) * (4 - 2) + 3 == 21

这表示最后一级是块映射

根据上下文,调用函数 __create_page_tables 会生成3级映射,可以通过 SWAPPER_PGTABLE_LEVELS == 3 分析出来
PGD + PMD + PTE(最后一级是块映射) + 页内偏移
有效位宽分别为 9 + 9 + 9 + 21 == 48

第七个参数 tmp1 ,用于函数内部作为临时变量

下面开始分析宏的详细内容

代码分析

第18行调用了宏定义 phys_to_pte,该宏的定义如下

	.macro	phys_to_pte, pte, phys
#ifdef CONFIG_ARM64_PA_BITS_52
	/*
	 * We assume \phys is 64K aligned and this is guaranteed by only
	 * supporting this configuration with 64K pages.
	 */
	orr	\pte, \phys, \phys, lsr #36
	and	\pte, \pte, #PTE_ADDR_MASK
#else
	mov	\pte, \phys
#endif
	.endm

我们没有使能 CONFIG_ARM64_PA_BITS_52,而是使能了 CONFIG_ARM64_PA_BITS_48,所以该宏就是把 rtbl,也就把是下一级的页表物理地址存放在 tmp1 里面
这说明  rtbl 还可能有用,我们下面的操作会修改它,所以放在临时变量里面进行后续处理

第19行将 tmp1 与 flags 进行或操作,也就是说,将页表基地址与页表属性组合在一起,由于页表基地值的有效位和页表属性的有效位在不同的位域里面,所以可以认为是缝合在一起。

第20行是最关键的一步,将上一步逻辑运算得出的缝合怪,也就是下一级页表基地址+页表属性存储在本级页表的指定的表项里面。
其中,指定的表项由 index 决定,index 是起始索引,由于每个表项的大小是8B,所以表项的 index 每次需要自增8,也就是逻辑左移3

第21行开始准备下一个表项要写的内容,在注释部分里面我们描述过,inc 是步长,所以该语句执行完毕 rtbl 成为了下一级页表第二个页面的基地址。
这个操作说明,rtbl 也会修改,按照这样操作,该宏执行完毕后,rtbl 指向下下级页表的基地址

第22行将索引值自增1,准备下一次的写页表处理操作

第23行将下一步要处理的索引与结束索引进行比较,如果前者较小的话说明没有到结束索引,所以跳转到18行重新执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值