1. QEMU RISC-V 环境搭建:从源码到第一个虚拟机

各位同学,咱们直接进入正题。做 RISC-V 开发,第一件事就是把环境搭起来。这一步要是没弄好,后面所有调试、分析、故障排查都无从谈起。我个人习惯是「源码编译 QEMU + 独立安装工具链」,这样可控性最强。

本章核心目标: 从零搭建一套可用的 QEMU RISC-V 开发环境,并成功启动第一个虚拟机。

1.1 为什么非要自己编译 QEMU?

你可能会问:apt install qemu-system 不香吗?嗯,这里要注意——发行版自带的 QEMU 版本通常比较老,而且很多调试功能没打开。我在项目中遇到过因为 QEMU 版本太低,导致 GDB 连不上模拟器的问题,查了整整两天。

自己编译的好处有三个:

  • 版本可控:想用 7.2 还是 8.0,你说了算
  • 调试符号全开:--enable-debug 编译出来的 QEMU 能输出更详细的日志
  • 自定义设备:后面章节我们会往 QEMU 里加自定义外设,必须源码编译

1.2 编译 QEMU(RISC-V 目标)

先拉源码。我建议用 Git 克隆,方便后续切分支。

git clone https://gitlab.com/qemu-project/qemu.git
cd qemu
git checkout stable-8.0  # 我用的是 8.0,稳定且功能齐全

配置编译选项。这里我列一个「生产级」配置,既保证性能,又保留调试能力:

./configure \
  --target-list=riscv64-softmmu \
  --enable-debug \
  --enable-debug-info \
  --enable-kvm \
  --enable-virtfs \
  --enable-slirp
配置项 作用 我的建议
--target-list=riscv64-softmmu 只编译 RISC-V 64 位系统模拟 省时间,别全编译
--enable-debug 开启 QEMU 内部调试日志 必开,后面分析日志全靠它
--enable-kvm 支持 KVM 加速 有硬件虚拟化就开
--enable-slirp 用户态网络栈 方便虚拟机上网
注意: 编译依赖包别漏了。Ubuntu 下执行 sudo apt install ninja-build libglib2.0-dev libpixman-1-dev。我吃过亏,configure 通过了,make 到一半报错,就是因为缺 libpixman。

编译安装:

make -j$(nproc)
sudo make install

验证一下:

qemu-system-riscv64 --version

看到版本号输出,说明 QEMU 编译成功。

1.3 RISC-V 工具链安装

工具链我推荐两种方式,看你的场景选:

方式 适用场景 安装命令
发行版包管理器 快速验证、学习 sudo apt install gcc-riscv64-linux-gnu
源码编译(riscv-gnu-toolchain) 生产环境、定制优化 见下方步骤

我个人倾向源码编译,因为可以控制 GCC 版本和 ABI 配置。但如果你只是跑个 Hello World,用包管理器就够了。

源码编译步骤:

git clone https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --enable-multilib
make -j$(nproc)
sudo make install
小技巧: 编译工具链很耗时,我一般用 screen 或 tmux 挂后台。曾经有一次编译到 90% 时 SSH 断了,心态崩了。从那以后,所有长时间编译我都用 tmux。

验证工具链:

/opt/riscv/bin/riscv64-unknown-linux-gnu-gcc --version

1.4 启动第一个 RISC-V 虚拟机

环境搭好了,咱们跑个真正的 RISC-V Linux 看看。你需要三个东西:

  • OpenSBI:RISC-V 的底层固件,负责引导
  • U-Boot:引导加载程序
  • 根文件系统镜像:我用 Buildroot 生成的最小系统

下载预编译好的镜像(省时间):

wget https://github.com/riscv-software-src/opensbi/releases/download/v1.2/opensbi-1.2-rv64-binaries.tar.xz
tar xf opensbi-1.2-rv64-binaries.tar.xz

启动命令:

qemu-system-riscv64 \
  -machine virt \
  -cpu rv64 \
  -m 2G \
  -smp 2 \
  -bios opensbi-1.2-rv64-binaries/share/opensbi/lp64/generic/firmware/fw_jump.bin \
  -kernel u-boot.bin \
  -drive file=rootfs.ext2,format=raw,id=hd0 \
  -device virtio-blk-device,drive=hd0 \
  -nographic

看到 OpenSBI 的启动日志,然后进入 U-Boot,最后出现 Linux 登录提示符——恭喜,你的第一个 RISC-V 虚拟机跑起来了!

关键输出: 你会看到类似 OpenSBI v1.2、Linux version 6.1.0 这样的日志。这些日志后面章节会反复分析,先混个眼熟。

1.5 本章知识结构图

下面这张图把整个环境搭建的流程串起来了,建议你保存下来对照操作:

QEMU RISC-V 环境搭建流程 1. 获取 QEMU 源码 2. 获取工具链源码 3. 获取固件/镜像 4. 编译 QEMU 5. 编译工具链 6. 准备 OpenSBI/U-Boot 7. 验证 QEMU 版本 8. 验证 GCC 版本 9. 检查镜像完整性 10. qemu-system-riscv64 启动 -machine virt -cpu rv64 -m 2G ✅ 第一个 RISC-V 虚拟机启动成功

1.6 常见问题与避坑

环境搭建这一步,我见过太多人卡住。列几个高频问题:

问题1:configure 报错 "glib-2.0 not found"
原因:缺 libglib2.0-dev。执行 sudo apt install libglib2.0-dev 即可。
问题2:启动后黑屏,没有任何输出
原因:多半是 -bios 参数指向的 OpenSBI 文件不对,或者 -nographic 没加。检查文件路径,确认使用 fw_jump.bin 而非 fw_payload.bin。
问题3:编译 QEMU 时 make 卡住不动
我曾经在 4GB 内存的机器上编译,直接 OOM 了。建议至少 8GB 内存,或者用 make -j2 降低并行度。

1.7 验证环境是否就绪

最后,我建议你做一个快速自检。跑下面这条命令,如果能正常输出,说明环境基本没问题:

qemu-system-riscv64 -machine virt -cpu rv64 -m 256M -nographic -bios /dev/null

这条命令不会启动任何系统,但会输出 QEMU 的 monitor 提示符。看到 (qemu) 就对了。

环境就绪清单:
  • ✅ QEMU 8.0 编译安装完成
  • ✅ RISC-V 工具链可用(gcc、ld、objdump)
  • ✅ OpenSBI 和 U-Boot 镜像已下载
  • ✅ 根文件系统镜像已准备
  • ✅ 能启动到 Linux 登录提示符