ARM Cortex-A53从EL3安全态切换至EL1非安全态触发异常问题
ARM Cortex-A53 EL3安全态到EL1非安全态切换异常排查
问题背景
仅进行EL3到EL1的安全态切换时,代码可正常执行ERET跳转至el1_entry_aarch64并进入__main。但在secure_to_ns中添加SCR_EL3的NS位配置后,执行el1_entry_aarch64的NOP指令时触发异常。
已知信息:
- 程序运行内存区间:0xF8040000至0xF80AFFFF
- 已配置0xF8090000至0xF80B0000为非安全访问区域,ERET后执行代码均位于该区域
- 已排除段间跳转影响
正常工作的代码(EL3到EL1安全态切换)
el1_entry_aarch64: NOP NOP NOP // we can use the same vector table in this example, but in general // each combination of Exception level, Security state, and Execution state // will need a new vector table LDR x0, =vectors MSR VBAR_EL1, x0 //we must ensure that floating point register accesses are not trapped //since the c library for AArch64-v8A uses them MOV x0, #(0x3 << 20) MSR CPACR_EL1, x0 B __main secure_to_ns: MOV w1, #0 // Initial value of register is unknown ORR w1, w1, #(1 << 11) // set ST bit (disable trapping of timer control registers) ORR w1, w1, #(1 << 10) // set RW bit (next lower EL in aarch64) ORR w1, w1, #(1 << 3) // Set EA bit (SError routed to EL3) ORR w1, w1, #(1 << 2) // Set FIQ bit (FIQs routed to EL3) ORR w1, w1, #(1 << 1) // Set IRQ bit (IRQs routed to EL3) MSR SCR_EL3, x1 MSR SCTLR_EL1, xzr LDR x0, =el1_entry_aarch64 MOV x1, #0x5 MSR ELR_EL3, x0 // where to branch to when exception completes MSR SPSR_EL3, x1 // set the program state for this point to a known value ERET
触发异常的代码(添加NS位配置)
secure_to_ns: MOV w1, #0 // Initial value of register is unknown ORR w1, w1, #(1 << 11) // set ST bit (disable trapping of timer control registers) ORR w1, w1, #(1 << 10) // set RW bit (next lower EL in aarch64) ORR w1, w1, #(1 << 3) // Set EA bit (SError routed to EL3) ORR w1, w1, #(1 << 2) // Set FIQ bit (FIQs routed to EL3) ORR w1, w1, #(1 << 1) // Set IRQ bit (IRQs routed to EL3) ORR w1, w1, #1 // Set NS bit (lower EL in non Secure state) MSR SCR_EL3, x1 MSR SCTLR_EL1, xzr LDR x0, =el1_entry_aarch64 MOV x1, #0x5 MSR ELR_EL3, x0 // where to branch to when exception completes MSR SPSR_EL3, x1 // set the program state for this point to a known value ERET
排查方向与解决方案
检查SCTLR_EL1的非安全态配置
切换到非安全态时,SCTLR_EL1不能直接设为xzr(全0)。非安全态下该寄存器的M(MMU使能)、C(数据缓存使能)、I(指令缓存使能)等关键位需正确配置,全0会导致指令获取或内存访问异常。建议参考Cortex-A53手册设置初始值:MOV x0, #(1 << 0) | (1 << 2) | (1 << 3) | (1 << 12) // M=1, C=1, I=1, SA=1 MSR SCTLR_EL1, x0确认非安全态的MMU/内存映射配置
安全态的内存配置不会继承到非安全态,需单独为非安全态配置页表,确保0xF8090000-0xF80B0000区域被映射为可执行、可读写属性,并完成TTBR0_EL1/TTBR1_EL1的寄存器配置。检查SPSR_EL3的配置完整性
当前SPSR_EL3 = #0x5仅指定了EL1h模式,需补充设置DAIF位掩码,避免未预期的异常触发:MOV x1, #0x5 | (0b1111 << 6) // EL1h + 禁用FIQ/IRQ/SError/DAIF MSR SPSR_EL3, x1验证向量表的非安全态可用性
非安全态下VBAR_EL1指向的向量表必须位于非安全内存区域,且异常处理入口需适配非安全态环境,不能直接复用安全态的向量表逻辑。
内容的提问来源于stack exchange,提问作者lsy
相关产品推荐
相关产品推荐

