展示代码
#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

1861

被折叠的 条评论
为什么被折叠?



