QEMU加载起始地址在设备内存的Arm TrustZone文件失败问题咨询
问题原因
QEMU virt 机器默认的物理地址映射中,0x00000000 到 0x3fffffff 区间属于MMIO设备预留地址段,除了少量BootROM、外设寄存器、32KB Secure SRAM之外,没有映射普通可读写RAM。你指定的tz.mbn加载地址0x14680000正好落在这段无RAM映射的区间,loader设备写入数据时会直接触发总线错误,导致加载失败。
不要尝试修改ELF文件的加载入口,TrustZone镜像内存在大量硬编码的地址指针、页表项、异常向量偏移,强行修改入口地址就算加载成功也无法正常运行。
可行配置方案
优先选择方案2,对原有镜像加载逻辑影响最小。
方案1:调整全局RAM起始地址(适合所有镜像都在低地址的场景)
QEMU 6.0+版本的virt机器支持自定义RAM起始地址,可以把默认RAM的基地址从0x40000000挪到低于0x14680000的未占用区间,直接覆盖原有低地址空洞。
注意0x10000000到0x3fffffff是virt机器默认未分配的地址段,不会和UART、GIC、virtio等静态外设冲突,可安全使用。
配置示例:
qemu-system-aarch64 \ -machine virt,secure=true,virtualization=true,gic-version=3,ram-start=0x10000000,memory-backend=sysram \ -cpu cortex-a57 \ -smp 1 \ -object memory-backend-ram,id=sysram,size=3G \ -kernel boot.img \ -device loader,addr=0x80040000,cpu-num=0,file=./hyp.mbn \ -device loader,addr=0x14680000,cpu-num=0,file=./tz.mbn \ -nographic \ -S -s
该方案会修改全局内存映射,需要确认boot.img、hyp.mbn的硬编码加载地址是否落在新的RAM区间内,否则会出现其他镜像加载失败的问题。
方案2:单独映射指定地址RAM(推荐,无兼容问题)
不需要修改全局RAM配置,通过NUMA节点单独给0x14680000地址段映射一段独立RAM,专门用来放tz.mbn,原有0x40000000开始的RAM映射完全不变,不会影响kernel、hyp的加载运行。
配置示例:
qemu-system-aarch64 \ -machine virt,secure=true,virtualization=true,gic-version=3 \ -cpu cortex-a57 \ -smp 1 \ -m 3G \ -object memory-backend-ram,id=tz_ram,size=8M \ -numa node,memdev=tz_ram,addr=0x14680000 \ -kernel boot.img \ -device loader,addr=0x80040000,cpu-num=0,file=./hyp.mbn \ -device loader,addr=0x14680000,cpu-num=0,file=./tz.mbn \ -nographic \ -S -s
注意事项
- 分配给
tz_ram的size要比tz.mbn实际文件大小大1M以上,预留出bss段、栈空间的内存余量,避免运行时越界,可根据镜像实际大小调整数值 - 如果加载
hyp.mbn也报地址错误,说明0x80040000落在GICv3寄存器区间(0x08000000-0x08ffffff),可以用同样的方法单独给hyp分配一段低地址RAM,比如从0x14000000映射2M RAM放hyp,0x14680000放tz,完全避开外设地址区间 - 开启
secure=true配置后,这段单独映射的RAM默认会被标记为Secure世界可访问的普通内存,不会被当成设备内存触发权限异常
内容的提问来源于stack exchange,提问作者Icarus_Incarnate
相关产品推荐
相关产品推荐

