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

ARM64内核中MMU启用前后如何加载变量虚拟地址至寄存器?

ARM64汇编宏MMU开启后加载虚拟地址的解决方案

问题背景

编写了适用于ARM64的汇编宏write_mark,用于向调试缓冲区mydebug2写入标记数据,MMU启用前功能正常,但MMU开启后宏失效,经调试确认是因为加载mydebug2和myidx时使用的是物理地址,而非虚拟地址。

宏代码:

.macro write_mark, data
adr_l x25, mydebug2 // x25 = &mydebug2
adr_l x26, myidx // x26 = &myidx
ldr x27, [x26] // x27 = myidx
mov x26, \data // x26 = data
//add x27, x27, x27, LSL #1 // x27, 3 // to double word address
lsl x27, x27, #3 // x27, 3 // to double word address
add x25, x25, x27
str x26, [x25] // mydebug2[myidx] = data
adr_l x26, myidx // x26 = &myidx
ldr x27, [x26] // x27 = myidx
add x27, x27, 1 // x27(myidx) ++
str x27, [x26] // myidx++
.endm

调用方式:

adrp    x1, init_pg_dir
    write_mark 0x5555
    bl      __enable_mmu
    write_mark 0x6666

解决方案

方案1:区分MMU状态的宏版本

修改宏,增加参数控制是否使用虚拟地址加载,MMU开启前用物理地址(原有逻辑),MMU开启后直接加载虚拟地址:

.macro write_mark, data, use_virt=0
    .if \use_virt
        // MMU开启后,直接加载虚拟地址
        ldr x25, =mydebug2
        ldr x26, =myidx
    .else
        // MMU开启前,加载物理地址
        adr_l x25, mydebug2
        adr_l x26, myidx
    .endif
    ldr x27, [x26]
    mov x26, \data
    lsl x27, x27, #3
    add x25, x25, x27
    str x26, [x25]

    .if \use_virt
        ldr x26, =myidx
    .else
        adr_l x26, myidx
    .endif
    ldr x27, [x26]
    add x27, x27, 1
    str x27, [x26]
.endm

调用时指定参数:

adrp    x1, init_pg_dir
    write_mark 0x5555          // MMU未开启,用物理地址
    bl      __enable_mmu
    write_mark 0x6666, 1       // MMU已开启,用虚拟地址

方案2:自动检测MMU状态并切换地址

通过读取SCTLR_EL1寄存器的M位(第0位)判断MMU是否开启,自动切换物理/虚拟地址:

// 先定义虚拟地址与物理地址的偏移量,根据你的系统配置修改
.equ VIRT_OFFSET, 0xFFFFFF7F80000000  // 示例:虚拟基址0xFFFFFF8000000000 - 物理基址0x80000000

.macro write_mark, data
    adr_l x25, mydebug2
    adr_l x26, myidx

    // 检查MMU是否开启
    mrs x28, sctlr_el1
    tst x28, #(1 << 0)
    beq 1f  // MMU未开启,跳过偏移计算
    // MMU已开启,加上虚拟地址偏移
    add x25, x25, #VIRT_OFFSET
    add x26, x26, #VIRT_OFFSET
1:
    ldr x27, [x26]
    mov x26, \data
    lsl x27, x27, #3
    add x25, x25, x27
    str x26, [x25]

    adr_l x26, myidx
    mrs x28, sctlr_el1
    tst x28, #(1 << 0)
    beq 2f
    add x26, x26, #VIRT_OFFSET
2:
    ldr x27, [x26]
    add x27, x27, 1
    str x27, [x26]
.endm

方案3:调整链接脚本保证地址偏移一致

修改链接脚本,让数据段(包含mydebug2和myidx)的虚拟地址与物理地址的偏移和代码段完全一致。例如:

假设代码段物理地址为0x80000000,虚拟地址为0xFFFFFF8000000000,则数据段的虚拟地址应设为物理地址 + (0xFFFFFF8000000000 - 0x80000000)。这样adr_l宏在MMU开启后会自动基于PC的虚拟地址计算出正确的虚拟地址,无需修改宏代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:13:18