需要分析的代码
/*
* __cpu_setup
*
* Initialise the processor for turning the MMU on.
*
* Output:
* Return in x0 the value of the SCTLR_EL1 register.
*/
.pushsection ".idmap.text", "awx"
SYM_FUNC_START(__cpu_setup)
tlbi vmalle1 // Invalidate local TLB
dsb nsh
mov x1, #3 << 20
msr cpacr_el1, x1 // Enable FP/ASIMD
mov x1, #1 << 12 // Reset mdscr_el1 and disable
msr mdscr_el1, x1 // access to the DCC from EL0
isb // Unmask debug exceptions now,
enable_dbg // since this is per-cpu
reset_pmuserenr_el0 x1 // Disable PMU access from EL0
reset_amuserenr_el0 x1 // Disable AMU access from EL0
分析过程
CPACR_EL1
第14, 15行涉及的寄存器 CPACR_EL1, Architectural Feature Access Control Register 的位域 bits[21:20]
该寄存器的含义如下 Controls access to trace, SVE, Advanced SIMD and floating-point functionality.
bits[21:20] 的含义如下:
FPEN, bits [21:20]
Traps EL0 and EL1 accesses to the SVE, Advanced SIMD, and floating-point registers to EL1,
or to EL2 when it is implemented and enabled for the current Security state and HCR_EL2.TGE is 1,
from both Execution states.
该位域的值有多种组合,分别表达的含义是
0b00
This control causes any instructions at EL0 or EL1 that use the registers associated with SVE,
Advanced SIMD and floating-point execution to be trapped,
unless they are trapped by CPACR_EL1.ZEN.
0b01
This control causes any instructions at EL0 that use the registers associated with SVE,
Advanced SIMD and floating-point execution to be trapped, unless they are trapped by CPACR_EL1.ZEN,
but does not cause any instruction at EL1 to be trapped.
0b10
This control causes any instructions at EL0 or EL1 that use the registers associated with SVE,
Advanced SIMD and floating-point execution to be trapped, unless they are trapped by CPACR_EL1.ZEN.
0b11
This control does not cause any instructions to be trapped.
MDSCR_EL1
第16行和第17行涉及到了寄存器 mdscr_el1 的位域 bit12
该寄存器的含义如下
Monitor Debug System Control Register,也就是 Main control register for the debug implementation
bit12的含义如下
TDCC, bit [12]
Traps EL0 accesses to the DCC registers to EL1, from both Execution states.
0b0
This control does not cause any instructions to be trapped.
0b1
EL0 using AArch64: EL0 accesses to the MDCCSR_EL0, DBGDTR_EL0, DBGDTRTX_EL0, and DBGDTRRX_EL0 registers are trapped to EL1.
EL0 using AArch32: EL0 accesses to the DBGDSCRint, DBGDTRRXint, DBGDTRTXint, DBGDIDR, DBGDSAR, and DBGDRAR registers are trapped to EL1.
也就是说,位域bit12设置为1时,在EL0异常等级下,访问 MDCCSR_EL0, DBGDTR_EL0, DBGDTRTX_EL0, and DBGDTRRX_EL0 将会切换到 EL1 异常等级
enable_dbg
第19行涉及到 enable_dbg,定义如下
.macro enable_dbg
msr daifclr, #8
.endm
daifclr 涉及到 pstate 寄存器的 bits[9:6],分别是 DAIF,8对应 bit[9],表示清除调试掩码
PMU 和 AMU
第20行代码的注释是 Disable PMU access from EL0,入参为 x0
我们看一下宏定义的内容,x0 作为临时寄存器,入参的值并没有实际意义
/*
* reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
*/
.macro reset_pmuserenr_el0, tmpreg
mrs \tmpreg, id_aa64dfr0_el1
sbfx \tmpreg, \tmpreg, #ID_AA64DFR0_PMUVER_SHIFT, #4
cmp \tmpreg, #1 // Skip if no PMU present
b.lt 9000f
msr pmuserenr_el0, xzr // Disable PMU access from EL0
9000:
.endm
该宏定义首先获取寄存器 id_aa64dfr0_el1 的值存放在临时寄存器 tmpreg 里面,然后拷贝从 ID_AA64DFR0_PMUVER_SHIFT 开始的 4bit的数据到 tmpreg 里面,并且进行位扩展
ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0,该寄存器的作用是 Provides top level information about the debug system in AArch64 state.
ID_AA64DFR0_PMUVER_SHIFT 的定义如下
#define ID_AA64DFR0_PMUVER_SHIFT 8
根据寄存器的手册描述,位域 bits[11:8]的含义如下
PMUVer, bits [11:8]
Performance Monitors Extension version.
0b0000 Performance Monitors Extension not implemented.
0b0001 Performance Monitors Extension implemented, PMUv3.
0b0100 PMUv3 for Armv8.1. As 0b0001, and also includes support for:
• Extended 16-bit PMEVTYPER<n>_EL0.evtCount field.
• If EL2 is implemented, the MDCR_EL2.HPMD control bit.
0b0101 PMUv3 for Armv8.4. As 0b0100 and also includes support for the PMMIR_EL1 register.
0b0110 PMUv3 for Armv8.5. As 0b0101 and also includes support for:
• 64-bit event counters.
• If EL2 is implemented, the MDCR_EL2.HCCD control bit.
• If EL3 is implemented, the MDCR_EL3.SCCD control bit.
0b1111 IMPLEMENTATION DEFINED form of performance monitors supported, PMUv3 not supported. Arm does not recommend this value in new implementations.
从上述描述我们可以得知,只有当位域的值为0和-1的时候,才表示 PMUv3 没有效
所以宏定义里面判断,该位域的值小于1的时候,直接跳转到9000处,否则将寄存器 pmuserenr_el0 清零
PMUSERENR_EL0, Performance Monitors User Enable Register 的含义如下 Enables or disables EL0 access to the Performance Monitors.
用于控制用户模式(EL0)对性能监视单元(PMU)的访问权限,在这里将其清零,表示禁止在 EL0 异常等级下访问。
第22行与第21行很类似,只不过是操作的 AMU 相关的 id_aa64pfr0_el1 和 AMUSERENR_EL0 寄存器,其宏定义如下
/*
* reset_amuserenr_el0 - reset AMUSERENR_EL0 if AMUv1 present
*/
.macro reset_amuserenr_el0, tmpreg
mrs \tmpreg, id_aa64pfr0_el1 // Check ID_AA64PFR0_EL1
ubfx \tmpreg, \tmpreg, #ID_AA64PFR0_AMU_SHIFT, #4
cbz \tmpreg, .Lskip_\@ // Skip if no AMU present
msr_s SYS_AMUSERENR_EL0, xzr // Disable AMU access from EL0
.Lskip_\@:
.endm