慢慢欣赏arm64内核启动3 primary_entry之el2_setup代码第一部分

代码分析

分析完el2_setup的注释和代码段的位置之后,我们正式开始学习el2_setup的实现

SYM_FUNC_START(el2_setup)
	msr	SPsel, #1			// We want to use SP_EL{1,2}
	mrs	x0, CurrentEL
	cmp	x0, #CurrentEL_EL2
	b.eq	1f
	mov_q	x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1)
	msr	sctlr_el1, x0
	mov	w0, #BOOT_CPU_MODE_EL1		// This cpu booted in EL1
	isb
	ret

1:	mov_q	x0, (SCTLR_EL2_RES1 | ENDIAN_SET_EL2)
	msr	sctlr_el2, x0

异常等级

第二行需要参考ARM64的芯片手册,SPsel的值为0表示在任何异常等级下,都选择SP_EL0作为堆栈寄存器;
值为1表示选择异常等级对应的SP_ELX作为堆栈寄存器,X表示当前的异常等级
第三行表示将当前的异常等级存入到x0寄存器。
第四行表示将当前的异常等级与EL2比较。
第五行表示如果当前的等级就是EL2则跳转到标签为1的代码去执行;
否则如果不相等,也就是说,如果当前的异常等级为EL1,则继续执行。

设置SCTLR_ELX

第六行涉及到了一个系统寄存器SCTLR_EL1, System Control Register (EL1),我们又要查看芯片手册:
根据芯片手册手册描述,该寄存器提供了在EL0和EL1异常等级下,系统的异常级别控制,这里的系统,包括内存系统;
SCTLR_EL1_RES1表示该系统寄存器的保留位,这些保留位需要设置为1;

而ENDIAN_SET_EL1在代码的定义如下:

#ifdef CONFIG_CPU_BIG_ENDIAN
#define ENDIAN_SET_EL1		(SCTLR_EL1_E0E | SCTLR_ELx_EE)
#else
#define ENDIAN_SET_EL1		0
#endif

$ grep -rnw SCTLR_EL1_E0E arch/arm64/
arch/arm64/include/asm/sysreg.h:607:#define SCTLR_EL1_E0E		(BIT(24))

$ grep -rnw SCTLR_ELx_EE arch/arm64/
arch/arm64/include/asm/sysreg.h:571:#define SCTLR_ELx_EE    (BIT(25))

其中,E0E 表示设置 EL0下访问数据使用大端还是小端,0表示小端,1表示大端;

EE表示设置EL1下访问数据使用大端还是小端

对于ARM64架构,Linux内核会采用小端模式来处理数据,以确保与硬件平台的兼容性。

所以,在ARM64 Linux Kernel的配置里面,并没有使能该宏定义

$ cat .config | grep CONFIG_CPU_BIG_ENDIAN
# CONFIG_CPU_BIG_ENDIAN is not set

所以ENDIAN_SET_EL1表示使用小端。
紧接着第七行就表示,把刚才设置的值写入到 SCTLR_EL1 寄存器。
第八行表示,w0寄存器写入EL1,上一章节也就是el2_setup注释部分章节我们查看注释,w0作为出参,带出启动时的异常等级;
回到当前代码,由于当前是EL1异常等级,所以w0赋值为EL1是正确的;
紧接着第10行,如果当前的异常等级是EL1,w0也赋了正确的值,那也没有别的好说的了,直接返回。也就是说,如果当前的异常等级是EL1,设置完 SCTLR寄存器为小端即可。

但是如果当前的异常等级不是EL1,而是EL2则还要继续说道说道。
第12和第13行与第6和第7行很类似,只不过是将EL1换成了EL2;
查看芯片手册,该寄存器的含义是该寄存器提供了在EL2异常等级下,系统的级别控制,这里的系统,包括内存系统。

所以,同样需要将 SCTLR_EL2 寄存器相应的bit位设置为小端

#ifdef CONFIG_CPU_BIG_ENDIAN
#define ENDIAN_SET_EL2          SCTLR_ELx_EE
#else
#define ENDIAN_SET_EL2          0
#endif

$ grep -rn SCTLR_ELx_EE arch/arm64/
arch/arm64/include/asm/sysreg.h:571:#define SCTLR_ELx_EE    (BIT(25))

参考

参考1

Linux内核源码 ---- el2_setup源码解析
https://blog.csdn.net/aigourensheng/article/details/125704613

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值