x86 主机模拟 ARM64:从零搭建完整开发环境
ARM 模拟能做什么
在 x86 主机上模拟 ARM 架构,是 QEMU 最独特的能力之一。没有任何其他虚拟化软件能做到这一点。典型用途:
- 嵌入式开发:模拟 ARM 开发板(Raspberry Pi 类),在上面调试 u-boot、内核、驱动
- 移动端应用测试:模拟 arm64 Android 环境(虽然 Android Studio 有自带模拟器,但底层也是 QEMU)
- 跨平台编译验证:编译好的 ARM 二进制在用户态模拟里快速验证
- 学习 ARM 架构:写 ARM 汇编,在 QEMU 里单步调试
ARM 模拟的难点
ARM 模拟和 x86 模拟有两个关键差异:
- 加速器受限:x86 主机上模拟 ARM 时 TCG 是唯一选择(架构不同,硬件加速不适用)。性能较慢
- 板卡选型:ARM 没有统一的"PC"——每种板卡设备组合完全不同。QEMU 提供了几种通用板卡
QEMU 支持的 ARM 板卡
| 板卡名 | 说明 | 用途 |
|---|---|---|
virt | QEMU 虚拟 ARM 服务器板 | 跑通用 Linux 发行版,推荐 |
raspi2b | Raspberry Pi 2 Model B | 模拟树莓派 |
raspi3ap | Raspberry Pi 3 Model A+ | 模拟树莓派 |
versatilepb | ARM Versatile | 经典 ARM 开发板 |
vexpress-a15 | Vexpress Cortex-A15 | 嵌入式开发 |
aarch64 | 通用 AArch64 | 最通用 |
大多数场景用 -M virt 就够了——这是 QEMU 设计的"理想"ARM 服务器板,设备支持最完整。
模拟 ARM64 Linux(virt 板)
准备材料
- 内核镜像(vmlinuz)和 initramfs(initrd.img)——从 Ubuntu ARM64 ISO 里提取
- 根文件系统(rootfs)——qcow2 格式
- 可选:ARM64 ISO 用于全新安装
步骤一:创建根文件系统
qemu-img create -f qcow2 rootfs.qcow2 10G
步骤二:提取内核和 initrd
挂载 Ubuntu ARM64 ISO,从中提取:
casper/vmlinuz→ 重命名为 vmlinuz-arm64casper/initrd→ 重命名为 initrd-arm64
步骤三:启动
qemu-system-aarch64 \
-M virt \
-m 4G \
-cpu max \
-kernel vmlinuz-arm64 \
-initrd initrd-arm64 \
-drive file=rootfs.qcow2,format=qcow2,if=virtio \
-append "root=/dev/vda1 console=ttyAMA0" \
-netdev user,id=n0,hostfwd=tcp::2222-:22 \
-device virtio-net-pci,netdev=n0 \
-nographic
逐行解释:
-M virt:选 virt 板卡(ARM64 上最通用)-cpu max:暴露当前 QEMU 支持的最强 ARM CPU 特性-kernel+-initrd:直接引导内核,跳过 u-boot-append:内核参数,指定根分区和控制台-nographic:所有输出走终端(ttyAMA0 是 ARM64 的串口)
首次启动安装系统
如果 rootfs.qcow2 是空的,需要先引导 Ubuntu 安装器:
qemu-system-aarch64 \
-M virt -m 4G -cpu max \
-cdrom ubuntu-24.04-live-server-arm64.iso \
-drive file=rootfs.qcow2,format=qcow2,if=virtio \
-nic user,hostfwd=tcp::2222-:22 \
-nographic
安装完成后重启,用第一种命令引导新系统。
在 Apple Silicon Mac 上模拟 ARM
Apple Silicon 本身是 ARM64,QEMU 可以用 HVF 加速!
qemu-system-aarch64 \
-accel hvf \
-M virt -m 8G -cpu host \
-kernel vmlinuz \
-initrd initrd \
-drive file=rootfs.qcow2,format=qcow2 \
-append "root=/dev/vda1 console=ttyAMA0" \
-nographic
这是性能最高的 ARM 模拟方案——Apple Silicon 原生执行 ARM64 指令,性能接近物理机。
注意:
-cpu host在 Apple Silicon 上可能不可用。如果报特性不支持,换成-cpu max,pauth-impdef=on。
用户态 ARM 模拟
不需要完整系统,只是跑 ARM 编译的二进制:
# 安装用户态模拟器
sudo apt install qemu-user qemu-user-static
# 模拟运行
qemu-aarch64 ./my-arm64-binary
# 带根文件系统
qemu-aarch64-L /opt/arm64-rootfs ./my-arm64-binary
用户态模拟只翻译指令,共享宿主机的系统调用。速度比全系统模拟快得多。
GDB 调试 ARM 内核
QEMU 可以在启动时打开 GDB server,让你在 GDB 里单步调试 Guest 内核:
# QEMU 侧打开 GDB server
qemu-system-aarch64 \
-M virt -m 4G -smp 4 \
-kernel vmlinuz -initrd initrd \
-drive file=rootfs.qcow2,format=qcow2 \
-append "root=/dev/vda1 nokaslr" \
-s -S \
-nographic
# -s 在 1234 端口开 GDB server,-S 启动后暂停等待连接
另一个终端连上去:
# ARM GDB
aarch64-linux-gnu-gdb vmlinux
(gdb) target remote :1234
(gdb) b start_kernel
(gdb) continue
常见问题
Guest 里没有 eth0
virt 板卡的网卡在 Guest Linux 里叫 ens3(或 enp0s1),不是 eth0。Ubuntu 用 netplan,修改 /etc/netplan/*.yaml 配置。
u-boot 引导问题
用 -kernel 跳过 u-boot 是最简单的方式。如果必须用 u-boot(比如要测试 u-boot 本身),需要额外编译 u-boot.bin 并指定。
模拟速度慢
x86 主机上只能用 TCG,速度是 ARM 物理机的 5%~15%。建议:
- Guest 里跑轻量系统(Alpine、OpenWrt)
- 用
-accel tcg,thread=multi多线程翻译 - 分给 Guest 合理的 CPU 核数(不要给太多)
下一步
ARM 模拟通了?去 RISC-V 模拟 看看同样的套路怎么跑 RISC-V。