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

展示代码

#ifdef CONFIG_RELOCATABLE
#ifdef CONFIG_RELR
	mov	x24, #0				// no RELR displacement yet
#endif
	bl	__relocate_kernel
#ifdef CONFIG_RANDOMIZE_BASE
	ldr	x8, =__primary_switched
	adrp	x0, __PHYS_OFFSET
	blr	x8

	/*
	 * If we return here, we have a KASLR displacement in x23 which we need
	 * to take into account by discarding the current kernel mapping and
	 * creating a new one.
	 */
	pre_disable_mmu_workaround
	msr	sctlr_el1, x20			// disable the MMU
	isb
	bl	__create_page_tables		// recreate kernel mapping

	tlbi	vmalle1				// Remove any stale TLB entries
	dsb	nsh
	isb

	msr	sctlr_el1, x19			// re-enable the MMU
	isb
	ic	iallu				// flush instructions fetched
	dsb	nsh				// via old mapping
	isb

	bl	__relocate_kernel
#endif
#endif
	ldr	x8, =__primary_switched
	adrp	x0, __PHYS_OFFSET
	br	x8
SYM_FUNC_END(__primary_switch)

分析代码

第1和第2行涉及到编译宏 CONFIG_RELOCATABLE 和 CONFIG_RELR,我们先忽略

这样我们到了第34行,第34行将 __primary_switched 的内核链接地址存放在了 x8

第35行涉及到宏定义 __PHYS_OFFSET,
该宏定义在《慢慢欣赏arm64内核启动10 primary_entry之set_cpu_boot_mode_flag》和《慢慢欣赏arm64内核启动18 primary_entry之__create_page_tables代码第五部分》有介绍
其值为 0xFFFF 8000 1000 0000
adrp 指令将符号 __PHYS_OFFSET 所在的页面的基地址加载到寄存器 x0 中。在 ARM64 架构中,页面大小通常是 4KB,所以这个指令实际上是获取 __PHYS_OFFSET 地址所在的 4KB 页面的起始地址。

第36行 跳转到 __primary_switched 执行,参数为 x0 即 0xFFFF 8000 1000 0000
其中,br 用于无条件跳转,不保存返回地址,而 bl 用于带返回的跳转,会保存返回地址。

也就是说,作为 primary_entry 的最后一个函数 __primary_switch,执行了第36行而不返回,表示 primary_entry 结束了。

__primary_switched 的链接地址如下

$ cat System.map | grep __primary_switched
ffff8000115e0338 t __primary_switched

跳转函数落入 TTBR1_EL1 所在的地址空间,从 从 0xFFFF000000000000 到 0xFFFFFFFFFFFFFFFF
也就是说,后续的代码执行都在链接地址指向的空间执行。

参考

参考1

ARM64体系结构编程1-加载与存储指令
https://blog.csdn.net/qq_34207992/article/details/127200176

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值