QEMU 虚拟化完全指南 / 12 - ARM/RISC-V 仿真
12 - ARM/RISC-V 仿真
掌握使用 QEMU 进行 ARM64 和 RISC-V 架构的全系统仿真、交叉编译与嵌入式开发。
12.1 多架构仿真概述
QEMU 最强大的特性之一是跨架构仿真(Cross-architecture Emulation),可以在 x86_64 主机上运行 ARM、RISC-V、MIPS、PowerPC 等架构的操作系统和应用程序。
QEMU 多架构仿真支持:
主机 (x86_64 Linux)
├── qemu-system-aarch64 → ARM64 全系统仿真
├── qemu-system-arm → ARM32 全系统仿真
├── qemu-system-riscv64 → RISC-V 64 位仿真
├── qemu-system-riscv32 → RISC-V 32 位仿真
├── qemu-system-mips → MIPS 大端序仿真
├── qemu-system-mipsel → MIPS 小端序仿真
├── qemu-system-ppc64 → PowerPC 64 位仿真
├── qemu-system-s390x → IBM System z 仿真
└── qemu-system-sparc64 → SPARC 64 位仿真
支持的架构一览
| 架构 | 系统仿真 | 用户仿真 | 常见用途 |
|---|---|---|---|
| aarch64 (ARM64) | ✅ | ✅ | 移动/嵌入式/服务器开发 |
| arm (ARM32) | ✅ | ✅ | IoT/嵌入式 |
| riscv64 | ✅ | ✅ | RISC-V 开发 |
| riscv32 | ✅ | ✅ | RISC-V 嵌入式 |
| mips/mipsel | ✅ | ✅ | 路由器/嵌入式 |
| ppc64/ppc | ✅ | ✅ | IBM POWER 服务器 |
| s390x | ✅ | ❌ | IBM 大型机 |
| sparc64 | ✅ | ❌ | 传统 UNIX |
12.2 ARM64 (AArch64) 全系统仿真
安装 ARM64 仿真环境
# 安装 QEMU ARM64 系统仿真器
sudo apt install -y qemu-system-arm qemu-efi-aarch64
# 下载 ARM64 系统镜像(Debian 示例)
wget https://cdimage.debian.org/cdimage/cloud/sid/daily/latest/debian-sid-nocloud-arm64-daily.qcow2
# 或者使用 Ubuntu cloud 镜像
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-arm64.img
使用 UEFI 启动 ARM64 虚拟机
# 准备 UEFI 固件变量文件
cp /usr/share/AAVMF/AAVMF_VARS.fd my-arm64-vars.fd
# 创建磁盘
qemu-img create -f qcow2 arm64-disk.qcow2 20G
# 下载 ARM64 安装 ISO
wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-12.x-arm64-netinst.iso
# 启动安装
qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-m 4G \
-smp 4 \
-bios /usr/share/AAVMF/AAVMF_CODE.fd \
-drive if=pflash,format=raw,file=my-arm64-vars.fd \
-drive file=arm64-disk.qcow2,format=qcow2,if=virtio \
-cdrom debian-12.x-arm64-netinst.iso \
-boot order=d \
-device virtio-gpu-pci \
-device usb-ehci \
-device usb-kbd \
-device usb-mouse \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-display sdl
ARM64 启动后配置
安装完成后,去掉 -cdrom 参数从硬盘启动:
qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-m 4G \
-smp 4 \
-bios /usr/share/AAVMF/AAVMF_CODE.fd \
-drive if=pflash,format=raw,file=my-arm64-vars.fd \
-drive file=arm64-disk.qcow2,format=qcow2,if=virtio \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-nographic \
-append "console=ttyAMA0"
ARM64 机器类型
| 机器类型 | 说明 |
|---|---|
virt | 通用虚拟机(推荐,最灵活) |
virt-2.12 | virt 2.12 版本 |
virt,gic-version=3 | 指定 GIC 版本 |
raspi3b | Raspberry Pi 3 Model B |
raspi4b | Raspberry Pi 4 Model B |
xlnx-zcu102 | Xilinx ZCU102 开发板 |
sbsa-ref | SBSA 参考平台 |
ARM64 CPU 类型
# 查看支持的 CPU 类型
qemu-system-aarch64 -cpu help
# 常用 CPU:
# cortex-a53 - ARMv8, 低功耗
# cortex-a57 - ARMv8, 高性能
# cortex-a72 - ARMv8, Raspberry Pi 4
# cortex-a76 - ARMv8.2, 高性能
# max - 支持所有特性(最快)
12.3 RISC-V 全系统仿真
安装 RISC-V 仿真环境
# 安装 QEMU RISC-V 系统仿真器
sudo apt install -y qemu-system-misc
# 验证
qemu-system-riscv64 --version
qemu-system-riscv32 --version
RISC-V 64 位虚拟机
# 下载 RISC-V 预编译镜像
# 使用 openEuler 或 Fedora RISC-V 镜像
wget https://mirror.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS/riscv64/images/openEuler-22.03-V1-base-qemu-riscv64.qcow2
# 下载 OpenSBI + U-Boot 固件
wget https://mirror.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS/riscv64/images/fw_payload-uboot-qemu-riscv64.bin
# 启动 RISC-V 虚拟机
qemu-system-riscv64 \
-M virt \
-cpu rv64 \
-m 4G \
-smp 4 \
-bios fw_payload-uboot-qemu-riscv64.bin \
-drive file=openEuler-22.03-V1-base-qemu-riscv64.qcow2,format=qcow2,if=virtio \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-nographic
RISC-V 无固件直接启动
# 使用内核直接启动(无需 U-Boot)
qemu-system-riscv64 \
-M virt \
-cpu rv64 \
-m 2G \
-smp 2 \
-kernel /path/to/Image \
-initrd /path/to/initrd.img \
-append "root=/dev/vda rw console=ttyS0" \
-drive file=riscv64-rootfs.qcow2,format=qcow2,if=virtio \
-nographic
RISC-V CPU 类型
| CPU 类型 | 说明 |
|---|---|
rv64 | 基础 RV64GC |
rv32 | 基础 RV32GC |
rv64,v=true | 启用向量扩展 (V) |
rv64,zba=true,zbb=true | 位操作扩展 |
12.4 交叉编译环境
安装交叉编译工具链
# ARM64 交叉编译
sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
sudo apt install -y binutils-aarch64-linux-gnu
# RISC-V 交叉编译
sudo apt install -y gcc-riscv64-linux-gnu g++-riscv64-linux-gnu
sudo apt install -y binutils-riscv64-linux-gnu
# ARM32 交叉编译
sudo apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
交叉编译示例
# 编写测试程序
cat > hello.c << 'EOF'
#include <stdio.h>
int main() {
printf("Hello from cross-compiled binary!\n");
printf("Architecture: ");
#if defined(__aarch64__)
printf("ARM64\n");
#elif defined(__riscv) && __riscv_xlen == 64
printf("RISC-V 64\n");
#elif defined(__arm__)
printf("ARM32\n");
#else
printf("Unknown\n");
#endif
return 0;
}
EOF
# 交叉编译 ARM64
aarch64-linux-gnu-gcc -o hello-arm64 hello.c -static
# 交叉编译 RISC-V
riscv64-linux-gnu-gcc -o hello-riscv64 hello.c -static
# 验证二进制文件架构
file hello-arm64
file hello-riscv64
# 使用 qemu-user 直接运行
qemu-aarch64 ./hello-arm64
qemu-riscv64 ./hello-riscv64
12.5 嵌入式开发
使用 QEMU 模拟嵌入式 Linux
# ARM Versatile 开发板
qemu-system-arm \
-M versatilepb \
-cpu arm1176 \
-m 256M \
-kernel zImage \
-dtb versatile-pb.dtb \
-drive file=rootfs.ext4,if=scsi,format=raw \
-append "root=/dev/sda rw console=ttyAMA0" \
-nographic
# RISC-V SiFive Unleashed
qemu-system-riscv64 \
-M sifive_u \
-m 8G \
-kernel Image \
-drive file=rootfs.img,format=raw,if=virtio \
-append "root=/dev/vda rw console=ttySIF0" \
-nographic
裸机程序调试
# 编写 ARM64 裸机程序
cat > boot.S << 'EOF'
.section .text
.global _start
_start:
ldr x0, =0x09000000 // UART 地址 (QEMU virt)
adr x1, msg
ldr w2, =len
1: ldrb w3, [x1], #1
strb w3, [x0]
subs w2, w2, #1
b.ne 1b
2: wfi
b 2b
msg: .ascii "Hello from bare metal ARM64!\n"
len = . - msg
EOF
# 编译
aarch64-linux-gnu-gcc -nostdlib -nostartfiles -ffreestanding \
-o boot.elf boot.S -Ttext=0x40000000
# 运行
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-m 128M \
-kernel boot.elf \
-nographic \
-semihosting
GDB 调试嵌入式程序
# 启动 QEMU 并等待 GDB 连接
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-m 256M \
-kernel firmware.elf \
-nographic \
-S -gdb tcp::1234
# 在另一个终端启动 GDB
aarch64-linux-gnu-gdb firmware.elf
# (gdb) target remote :1234
# (gdb) break main
# (gdb) continue
12.6 使用 QEMU 运行容器镜像
在 ARM64 环境中运行 Docker
# 在 ARM64 虚拟机中安装 Docker
ssh -p 2222 root@localhost
apt install docker.io
# 在虚拟机内运行 ARM64 容器
docker run --rm -it arm64v8/ubuntu:22.04 uname -a
# 输出: Linux ... aarch64 GNU/Linux
构建多架构镜像
# 在 x86_64 主机上使用 QEMU 构建 ARM64 镜像
docker buildx build --platform linux/arm64 -t myapp:arm64 .
详细的多架构构建请参见 第 15 章 - Docker 中的 QEMU。
12.7 常见问题与性能优化
性能对比
| 模式 | 相对性能 | 适用场景 |
|---|---|---|
| TCG (纯仿真) | 5-20% | 开发、测试、调试 |
| KVM (同架构) | 95-99% | 仅限相同架构 |
| 用户模式 | 10-30% | 程序测试 |
加速仿真性能
# 使用多线程 TCG(QEMU 6.0+)
qemu-system-aarch64 -accel tcg,thread=multi ...
# 增加 TCG 翻译缓存
qemu-system-aarch64 -accel tcg,tb-size=256 ...
# 使用 `-cpu max` 启用所有特性(减少模拟开销)
qemu-system-aarch64 -cpu max ...
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 启动极慢 | TCG 纯仿真 | 使用 cloud 镜像减小启动开销 |
| 网络不通 | 默认网络配置 | 检查 virtio-net 配置 |
| UEFI 启动失败 | 固件路径错误 | 检查 AAVMF/OVMF 路径 |
| 内核 panic | 内核不匹配 | 使用对应架构的内核 |
要点回顾
| 要点 | 核心内容 |
|---|---|
| ARM64 仿真 | qemu-system-aarch64 + virt 机器类型 |
| RISC-V 仿真 | qemu-system-riscv64 + OpenSBI/U-Boot |
| 交叉编译 | gcc-aarch64-linux-gnu / gcc-riscv64-linux-gnu |
| 用户模式 | qemu-aarch64 直接运行交叉编译的二进制 |
| 性能 | TCG 约 5-20%,仅用于开发测试 |
注意事项
性能限制: 跨架构 TCG 仿真性能仅为原生的 5-20%,不适合运行性能敏感型工作负载。如需在 ARM64 上运行高性能应用,建议使用物理 ARM64 服务器或云实例。
UEFI 固件: ARM64 虚拟机需要 UEFI 固件(AAVMF)。不同发行版的固件路径可能不同。
RISC-V 生态: RISC-V 生态仍在快速发展,某些软件可能尚未移植到 RISC-V。
扩展阅读
下一步
→ 13 - 用户模式:学习 qemu-user 静态翻译与 binfmt_misc 跨架构运行。