Assembly AArch64开关EL3>;非安全EL1问题

Assembly AArch64开关EL3>;非安全EL1问题,assembly,arm64,Assembly,Arm64,Cortex-A35处理器,AArch64模式。 在设置MMU和GIC之前,我尝试从EL3转到非安全EL1: msr VTTBR_EL2, xzr mov x0, SCR_EL3.RES1 or SCR_EL3.NS or SCR_EL3.RW or SCR_EL3.ST msr SCR_EL3, x0 mov x1, SPSR.M.AArch64_EL1h or SPSR_EL3.A or SPSR_EL3.I or SPSR_E

Cortex-A35处理器,AArch64模式。
在设置MMU和GIC之前,我尝试从EL3转到非安全EL1:

        msr VTTBR_EL2, xzr
        mov x0, SCR_EL3.RES1 or SCR_EL3.NS or SCR_EL3.RW or SCR_EL3.ST
        msr SCR_EL3, x0
        mov x1, SPSR.M.AArch64_EL1h or SPSR_EL3.A or SPSR_EL3.I or SPSR_EL3.F
        msr SPSR_EL3, x1
        adr x2, __el1
        msr ELR_EL3, x2
        ; all other system registers are set to their reset values. 
        ; SCTLR_EL1 = 0x00C50838
        ; HCR_EL2   = 0x0000000000000002

        eret

__el1:
        mov x10, 0xff220000  ; this simply turns on the LED on the board, 
        mov w11, 0x0020      ; for testing only
        str w11, [x10, 4]    ;
        str w11, [x10, 0]    ;
        b.al $ 
切换到安全EL1(
SCR_EL3.NS
未设置)工作正常,LED亮起。当我尝试转到不安全的EL1时,它不起作用

设置
HCR\u EL2.RW
也不起作用:

        mov x0, HCR_EL2.RW
        msr HCR_EL2, x0

我缺少什么?

您缺少ARMv8的异常级别和安全状态实现

无法直接更改EL3(安全)->EL1(不安全)

有两种可能的方式达到EL1:

  • EL3(安全)->EL1(安全)
  • EL3(安全)->EL2(不安全)->EL1(不安全)

    • 您缺少ARMv8的异常级别和安全状态实现

      无法直接更改EL3(安全)->EL1(不安全)

      有两种可能的方式达到EL1:

      • EL3(安全)->EL1(安全)
      • EL3(安全)->EL2(不安全)->EL1(不安全)

      我正在研究覆盆子皮3,最后终于把它做好了

      我看不出你的代码有什么不同,除非你没有设置堆栈指针。SP_EL1的重置值基本上是随机的,不一定是16字节对齐的

      这对我很有用:

      设置:

      #define get_system_reg( name, value ) asm ( "mrs %[v], "#name : [v] "=&r" (value) )
      #define set_system_reg( name, value ) asm ( "msr "#name", %[v]" : : [v] "r" (value) )
      #define modify_system_reg( name, bits, set ) asm ( "mrs x4, "#name \
                                                       "\nbic x4, x4, %[b]" \
                                                       "\norr x4, x4, %[s]" \
                                                       "\nmsr "#name", x4" \
                                                       : \
                                                       : [b] "r" (bits) \
                                                       , [s] "r" (set) \
                                                       : "x4" )
      
      asm volatile ( "msr VBAR_EL3, %[table]\n" : : [table] "r" (VBAR_EL3) );
      asm volatile ( "msr VBAR_EL2, %[table]\n" : : [table] "r" (VBAR_EL2) );
      asm volatile ( "msr VBAR_EL1, %[table]\n" : : [table] "r" (VBAR_EL1) );
      
      // Make lower levels 64-bit
      modify_system_reg( scr_el3, (1 << 10), (1 << 10) ); // Set RW (64-bit)
      
      // Some stacks at random memory locations
      set_system_reg( sp_el2, 0x200000 );
      set_system_reg( sp_el1, 0x300000 );
      set_system_reg( sp_el0, 0x400000 );
      
      在非安全el1上运行aarch64代码

      set_system_reg( elr_el3, example_a64 );
      set_system_reg( spsr_el3, EL1t );
      modify_system_reg( scr_el3, 1, 1 ); // Set NS bit
      modify_system_reg( hcr_el2, (1 << 31), (1 << 31) ); // Set RW (64-bit)
      asm ( "eret" );
      
      set_system_reg(elr_el3,示例_a64);
      设置系统注册表(spsr el3,EL1t);
      修改系统注册表(scr el3,1,1);//设置NS位
      
      modify_system_reg(hcr_el2,(1我正在使用树莓皮3,最终得到了正确的结果

      我看不出你的代码有什么不同,除非你没有设置堆栈指针。SP_EL1的重置值基本上是随机的,不一定是16字节对齐的

      这对我很有用:

      设置:

      #define get_system_reg( name, value ) asm ( "mrs %[v], "#name : [v] "=&r" (value) )
      #define set_system_reg( name, value ) asm ( "msr "#name", %[v]" : : [v] "r" (value) )
      #define modify_system_reg( name, bits, set ) asm ( "mrs x4, "#name \
                                                       "\nbic x4, x4, %[b]" \
                                                       "\norr x4, x4, %[s]" \
                                                       "\nmsr "#name", x4" \
                                                       : \
                                                       : [b] "r" (bits) \
                                                       , [s] "r" (set) \
                                                       : "x4" )
      
      asm volatile ( "msr VBAR_EL3, %[table]\n" : : [table] "r" (VBAR_EL3) );
      asm volatile ( "msr VBAR_EL2, %[table]\n" : : [table] "r" (VBAR_EL2) );
      asm volatile ( "msr VBAR_EL1, %[table]\n" : : [table] "r" (VBAR_EL1) );
      
      // Make lower levels 64-bit
      modify_system_reg( scr_el3, (1 << 10), (1 << 10) ); // Set RW (64-bit)
      
      // Some stacks at random memory locations
      set_system_reg( sp_el2, 0x200000 );
      set_system_reg( sp_el1, 0x300000 );
      set_system_reg( sp_el0, 0x400000 );
      
      在非安全el1上运行aarch64代码

      set_system_reg( elr_el3, example_a64 );
      set_system_reg( spsr_el3, EL1t );
      modify_system_reg( scr_el3, 1, 1 ); // Set NS bit
      modify_system_reg( hcr_el2, (1 << 31), (1 << 31) ); // Set RW (64-bit)
      asm ( "eret" );
      
      set_system_reg(elr_el3,示例_a64);
      设置系统注册表(spsr el3,EL1t);
      修改系统注册表(scr el3,1,1);//设置NS位
      
      修改系统注册表(hcr\U el2)(1您可以直接从EL3安全到EL0安全,为什么不从EL3到非安全EL0?当然,假设您已经设置了所有el2寄存器。“在设置MMU和GIC之前”,我假设关于启动的问题,在那一阶段没有设置。我明白你的意思。我想说的是,我认为EL2寄存器是否由EL2或EL3上运行的代码设置并不重要,只要它们是在尝试进入较低的EL之前设置好的。当我从EL2开始工作时,我就能证明这一点!你可以从EL3 se开始治疗到EL0直接安全,为什么不从EL3到非安全EL0?当然,假设您已经设置了所有EL2寄存器。“在设置MMU和GIC之前”,我假设关于启动的问题,在那一阶段没有设置。我明白你的意思。我想说的是,我认为如果EL2寄存器是由EL2或EL3上运行的代码设置的,这并不重要,只要它们是在试图进入较低的EL之前设置好的。当我从EL2开始工作时,我就能证明这一点!我被困在同样的地方。每次我尝试,我在ESR_EL3(或ESR_EL2,如果我尝试在64位或32位模式下分两步进入非安全EL1或EL0)中获得31000000,这是“非法执行状态”。你找到神奇的数字了吗?你是否设置了转换表并至少启用了MMU(有或没有缓存)在EL2,对于第二阶段的转换表?我不知道没有转换表的非安全EL0&1是如何工作的。DDI0487C中的伪代码只显示了PSTATE.IL设置为1的两个位置,在aarch32/functions/system/aarch32.WriteModeByInstr中,但由于IllegaleException,我没有运行任何32位代码,在shared/functions/system/SetPSTATEFromPSR中nReturn(spsr)返回true。我也被困在同样的地方。每次我尝试,我在ESR_EL3(或ESR_EL2,如果我尝试分两步以64位或32位模式到达不安全的EL1或EL0)中得到了3000000,这是“非法执行状态”。你找到了神奇的数字了吗?你设置了转换表并至少启用了MMU吗(带或不带缓存)在EL2,对于第二阶段的转换表?我不知道没有转换表的非安全EL0&1是如何工作的。DDI0487C中的伪代码只显示了PSTATE.IL设置为1的两个位置,在aarch32/functions/system/aarch32.WriteModeByInstr中,但由于IllegaleException,我没有运行任何32位代码,在shared/functions/system/SetPSTATEFromPSR中nReturn(spsr)返回true。