You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64从EL2切换至EL1时.data段被清零的原因排查

RK3588(Radxa RockPi 5b)EL1模式下.data段被清零问题解决

问题背景

在Radxa RockPi 5b(RK3588)上通过Uboot启动裸机应用,启动命令为:

fatload mmc 1 0x8300000 rk3588.bin
go 0x8300000

自定义printf函数在EL2下完全正常,但切换到EL1后出现异常:

  • .rodata段数据(字符串字面量、立即数)可正常打印
  • 局部变量可正常使用
  • 全局变量(.data段)读取值全为0,直接访问.data段物理地址也返回0

切换EL1的汇编代码如下:

prepare_el1:   
    ldr x0, =((1 << 31) | (1 << 41) | (1 << 40))
    msr hcr_el2, x0
    isb

    msr sctlr_el1, xzr
    isb

    ldr x0, =((7<<6) | 5)
    msr spsr_el2, x0
    isb

    adr x0, entry_el1
    msr elr_el2, x0
    isb
    eret

临时重定位程序到其他地址后,.data段可正常访问,但未明确根本原因。

核心原因分析

问题出在HCR_EL2的TGE位配置以及EL1的内存访问模式:

  1. 你设置了HCR_EL2的TGE位(bit41),这会让EL1进入Guest虚拟化模式
  2. 此时即使EL1关闭MMU(SCTLR_EL1.M=0),CPU访问的是中间物理地址(IPA),而非直接物理地址(PA)
  3. Uboot在EL2下的阶段2页表(用于Guest地址转换)未正确映射0x8300000附近的.data段区域:要么该区域未被映射,要么属性被设为只读/清零,导致EL1访问时返回0
  4. 重定位到其他地址后,该地址不在阶段2页表的限制范围内,因此能正常访问.data段

解决步骤

方案1:关闭Guest模式(推荐)

修改HCR_EL2的配置,移除TGE位(bit41),让EL1运行在Non-Guest模式,此时关闭MMU时直接访问物理地址,和EL2的访问逻辑一致:

prepare_el1:   
    ; 移除(1 << 41),保留RW位(bit31)和TWED位(bit40)
    ldr x0, =((1 << 31) | (1 << 40))
    msr hcr_el2, x0
    isb

    msr sctlr_el1, xzr
    isb

    ldr x0, =((7<<6) | 5)
    msr spsr_el2, x0
    isb

    adr x0, entry_el1
    msr elr_el2, x0
    isb
    eret

方案2:配置EL2阶段2页表

如果你需要保留Guest模式,需在EL2中为.data段所在的物理地址范围配置阶段2页表,将其标记为:

  • Normal Memory类型
  • 读写权限
  • 非执行属性
    确保EL1的IPA能正确映射到对应的PA,且属性允许读写。

补充优化

建议在EL1中正确配置SCTLR_EL1,开启缓存以提升性能:

; 在EL1入口处配置SCTLR_EL1
mov x0, #(1 << 0)      ; M位:开启MMU(如果需要)
orr x0, x0, #(1 << 2)  ; C位:开启数据缓存
orr x0, x0, #(1 << 12) ; I位:开启指令缓存
msr sctlr_el1, x0
isb

内容的提问来源于stack exchange,提问作者SONGYJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:29:57