微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AArch64转EL3>非安全EL1问题

如何解决AArch64转EL3>非安全EL1问题

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,0]    ;
        b.al $ 

切换到安全 EL1(SCR_EL3.NS 未设置)工作正常并且 LED 亮起。当我尝试转到非安全 EL1 时它不起作用。

设置 HCR_EL2.RW 也不起作用:

        mov x0,HCR_EL2.RW
        msr HCR_EL2,x0

我错过了什么?

解决方法

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

enter image description here

不能直接更改 EL3(安全)-> EL1(非安全)。

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

  • EL3(安全)-> EL1(安全)
  • EL3(安全)-> EL2(非安全)-> EL1(非安全)
,

我正在使用 Raspberry Pi 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,%[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 (M32_Svc = 0x1d3) 上运行 aarch32 代码:

set_system_reg( elr_el3,example_a32 ); // Address of the code
set_system_reg( spsr_el3,M32_Svc );    // Mode to run at
modify_system_reg( scr_el3,1,1 ); // Set NS bit
modify_system_reg( hcr_el2,(1 << 31),(0 << 31) ); // Clear RW (32-bit)
asm ( "eret" );

在非安全的 el1 上运行 aarch64 代码

set_system_reg( elr_el3,example_a64 );
set_system_reg( spsr_el3,EL1t );
modify_system_reg( scr_el3,(1 << 31) ); // Set RW (64-bit)
asm ( "eret" );

我的示例代码由一条 SVC 指令组成,在两种情况下都进入 VBAR_EL3 LOWER_AARCH64_SYNC 异常向量,大概是因为被跳过的 EL2 是 aarch64。 ESR_EL3 值是: 4e000000(AArch32 中的 SMC 指令执行),以及 5e000000(SMC 指令在 AArch64 状态下执行)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。