arm64_linux启动流程分析03_设定当前core的启动状态

接下来看el2_setup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ENTRY(el2_setup)
msr SPsel, #1 // We want to use SP_EL{1,2}
mrs x0, CurrentEL
cmp x0, #CurrentEL_EL2
b.eq 1f
mrs x0, sctlr_el1
CPU_BE( orr x0, x0, #(3 << 24) ) // Set the EE and E0E bits for EL1
CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
msr sctlr_el1, x0
mov w0, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1
isb
ret

1: mrs x0, sctlr_el2
......省略......

判断当前core的EL, 如果是EL1, 就设定使用little endian, CPU_BECPU_LE只有一条会编译进code. 之后返回BOOT_CPU_MODE_EL1, 如果EL2, 会初始化虚拟化相关的东西, 比较复杂, 先搁着.

1
2
adrp	x23, __PHYS_OFFSET
and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0

这段code跟kaslr有关, 我们下篇文章来着重讲这个. 先接着往下看set_cpu_boot_mode_flag:

1
2
3
4
5
6
7
8
9
10
set_cpu_boot_mode_flag:
adr_l x1, __boot_cpu_mode
cmp w0, #BOOT_CPU_MODE_EL2
b.ne 1f
add x1, x1, #4
1: str w0, [x1] // This CPU has booted in EL1
dmb sy
dc ivac, x1 // Invalidate potentially stale cache line
ret
ENDPROC(set_cpu_boot_mode_flag)

__boot_cpu_mode标签下保存了两个值

1
2
3
ENTRY(__boot_cpu_mode)
.long BOOT_CPU_MODE_EL2
.long BOOT_CPU_MODE_EL1

这段code的作用就是把保存的这两个值修改为一致, 且为当前CORE的启动EL, 其他CORE启动时也会运行这段code, 这样如果后面的CORE启动到了不同的EL就又会把这两个值修改为不一致, 从而可以判断出CPU的启动状态时不对的.