arm cortex-a53从el3安全切换到el1非安全问题

问题描述 投票:0回答:1

我正在尝试从 EL3 安全状态切换到 EL1 非安全状态。如果我不更改安全状态,而只执行从 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

执行ERET后,PC会跳转到

el1_entry_aarch64
,并从那里进入主函数。 除此之外,还有一些基本的堆栈初始化操作,我在这里省略了。

但是如果我添加切换安全状态的汇编代码,在el1_entry_aarch64中执行时,程序会进入异常。

secure_to_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

code demo

在el1_entry_aarch64函数内执行NOP指令时,程序进入异常。

我的程序运行在0xF8040000到0xF80AFFFF的内存范围内,也就是448KB的内存空间。通过某些配置,我将0xF8090000到0xF80B0000范围设置为非安全访问区域。

同时,我已经将相关的汇编代码放在了非安全区域中,也就是说eret指令之后执行的所有代码都在非安全区域内。

起初,我没有包含NOP汇编指令,但仍然遇到了这个问题。我一开始以为可能和不同段之间的跳转有关,所以加上了NOP指令。现在看来问题与跳转本身无关。

assembly arm boot trustzone
1个回答
0
投票

我认为从EL3直接切换到EL1是不可能的。根据 ARM 的官方裸机文档,您还应该设置虚拟机管理程序 (EL2)。特别是如果你想在 EL1 中使用定时器。这必须在 EL2 中完成。

在 EL3 中完成的 EL2 可能的(在 A53 上工作)设置:

el3_setup_el2:
    msr SCTLR_EL2, xzr
    msr HCR_EL2, xzr
    mrs x0, SCR_EL3
    orr x0, x0, #(1 << 10) /* Next lower exception level is AArch64 */
    orr x0, x0, #(1 << 0)  /* EL1/EL0 are in Non-secure state */
    msr SCR_EL3, x0
el3_exit:
    mov x0, xzr
    orr x0, x0, #(1 << 8)  /* Mask SError */
    orr x0, x0, #(1 << 7)  /* Mask IRQ */
    orr x0, x0, #(1 << 6)  /* Mask FIQ */
    mov x1, #0b01001       /* EL2 is in handler mode */
    orr x0, x0, x1
    msr SPSR_EL3, x0
    adr x0, el2_enter
    msr ELR_EL3, x0
    eret

在 EL2 中完成 EL1 的设置:

el2_setup_el1:
    mrs x0, HCR_EL2
    orr x0, x0, #(1 << 31) /* EL1 is AArch64 */
    msr HCR_EL2, x0
    /* Setup Stack for EL1 */
    ldr x0, =_stack_cpu0_el1_e
    msr SP_EL1, x0
    /* Setup Stack for EL0 */
    ldr x0, =_stack_cpu0_el0_e
    msr SP_EL0, x0
    
    mov x0, xzr
    orr x0, x0, #(1 << 29) /* RES1 */
    orr x0, x0, #(1 << 28) /* RES1 */
    orr x0, x0, #(1 << 23) /* RES1 */
    orr x0, x0, #(1 << 22) /* RES1 */
    orr x0, x0, #(1 << 20) /* RES1 */
    orr x0, x0, #(1 << 11) /* RES1 */
    orr x0, x0, #(1 << 4)  /* Enable SP aligment check for EL0 */
    orr x0, x0, #(1 << 3)  /* Enable SP aligment check for EL1 */
    orr x0, x0, #(1 << 1)  /* Enable aligment fault check */
    msr SCTLR_EL1, x0
    
el2_timer:
    /* Enable Timer for EL1 */
    mrs x0, CNTHCTL_EL2
    orr x0, x0, #(1 << 0)
    orr x0, x0, #(1 << 1)
    msr CNTHCTL_EL2, x0
    msr CNTVOFF_EL2, xzr
    
el2_exit:
    mov x0, xzr
    orr x0, x0, #(1 << 8) /* Mask SError */
    orr x0, x0, #(1 << 7) /* Mask IRQ */
    orr x0, x0, #(1 << 6) /* Mask FIQ */
    mov x1, #0b101        /* EL1 is in handler mode */
    orr x0, x0, x1
    msr SPSR_EL2, x0
    adr x0, el1_enter
    msr ELR_EL2, x0
    eret

我还建议在(示例)之前检查当前的异常级别:

el3_enter:
    mrs x0, CurrentEL
    and x0, x0, #0xC
    asr x0, x0, #2
    cmp x0, #3
    bne el2_enter
© www.soinside.com 2019 - 2024. All rights reserved.