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

ARMv8架构下BL1内部跳转至0x8000等地址系统挂起问题咨询

问题描述

我是ARM架构初学者,想要从BL1内部跳转到其他地址(例如0x8000)执行,首先在bl1_entrypoint中调用bl_main之后添加了两行代码:

bl  bl1_main

mov x0, #0x8000
br x0

但运行时br指令会导致系统挂起。

之后我尝试在bl1_main.c中新增jump()函数,在进入bl1_main()后调用该函数:

void jump(void)
{
    NOTICE("BL1: entering jump()...\n");
    console_flush();
    asm volatile ("mov x20, #0x8000\n");
    asm volatile ("br x20\n");
}

经JTAG测试,代码同样在br指令处停滞。

如果我将跳转地址从0x8000改为0x0,BL1会循环重复启动,符合预期;如果改为jump()函数自身的地址(通过bl1.dump查得为0xb00),运行也符合预期。

我不太理解为什么无法跳转到更远的地址,除了0x8000外我还测试了0x5000,同样无法正常跳转。

我放在0x8000(或0x5000)处的代码是从rom_trampoline.o提取的类似跳转代码,仅将跳转目标改为0x0,我的目标是测试BL1跳转到0x8000后再跳回0x0、循环往复的效果。

通过JTAG调试器,我在jump()地址0xb00处设置断点,程序会停在该地址的movz x20, #0x8000指令处,下一条就是br x20指令。当我单步跳过这条br指令时,JTAG调试器会与FPGA目标断开连接,状态栏报错Error - Failed asm stepin ! - Unknown Error (0x00000002)。这也不符合预期,因为启动初始在地址0x0处我可以正常单步执行,且mov指令本身无风险。

我还测试了无BL1参与的两个trampoline跳转代码:在0x0处放跳转到0x8000的代码,在0x8000处放跳回0x0的代码,测试结果符合预期,两个地址的断点会交替触发、无限循环。

目前我对BL1跳转到BL2的机制还不太熟悉,希望了解上述场景无法正常运行的原因。


根因说明

  1. ARMv8架构下MMU启用后,所有内存地址访问都会先经过页表属性校验,可执行的代码段必须配置为可执行(XN位未置1)、特权等级匹配、内存类型为正常内存的属性,也就是TF-A中定义的MT_CODE类型对应的配置。
  2. BL1在启动流程中会初始化MMU并配置默认的静态内存映射,默认映射仅覆盖BL1本身所在的地址区间、外设寄存器地址区间等必要区域,0x5000、0x8000这类地址不在默认映射范围内,或者被配置为不可执行的MT_DEVICE/MT_MEMORY_RW属性。
  3. 当CPU执行br指令跳转到未正确配置可执行属性的地址时,会触发指令预取中止异常,如果BL1未注册该异常的处理函数,就会直接挂死,表现为JTAG连接断开、系统停滞。
  4. 测试用的0x0、0xb00地址都属于BL1默认的代码段映射范围,已经配置了MT_CODE可执行属性,所以跳转可以正常运行。
  5. 无BL1参与的场景下MMU未启用,CPU访问地址采用物理地址直接寻址,不需要经过页表属性校验,所以跳转可以正常执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 07:39:03