3. QEMU RISC-V Virt机器启动

QEMU RISC-V Virt机器启动 学习卡片

任务说明

本案例使用QEMU的virt机器模拟RISC-V 64位处理器,目标是启动Linux内核并进入用户空间shell。我们将使用QEMU内置的virt机器定义,配合上游Linux内核的默认配置,完成从QEMU启动到Linux shell可交互的完整链路。

环境准备

需要以下组件:

  • QEMU(版本≥7.0,支持RISC-V virt机器)
  • Linux内核源码(版本≥5.15,推荐6.x)
  • 交叉编译工具链:riscv64-linux-gnu-(Debian/Ubuntu下安装包为gcc-riscv64-linux-gnu和binutils-riscv64-linux-gnu)
  • BusyBox(用于制作initramfs根文件系统)

实现步骤

1. 编译Linux内核

获取内核源码并配置RISC-V架构:

# 下载内核(以6.6版本为例)
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz
tar -xf linux-6.6.tar.xz
cd linux-6.6

# 设置交叉编译环境
export ARCH=riscv
export CROSS_COMPILE=riscv64-linux-gnu-

# 使用默认的virt配置
make defconfig

# 启用initramfs支持(后续步骤会生成initramfs)
# 编辑.config,确认以下选项已启用:
# CONFIG_BLK_DEV_INITRD=y
# CONFIG_DEVTMPFS=y
# CONFIG_DEVTMPFS_MOUNT=y

# 编译内核(使用多线程加速)
make -j$(nproc)

编译完成后生成arch/riscv/boot/Image内核镜像。

2. 制作initramfs根文件系统

使用BusyBox构建最小根文件系统:

# 下载并编译BusyBox
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1

# 静态编译配置
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j$(nproc)
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- install

# 构建initramfs目录结构
mkdir -p initramfs/{bin,sbin,etc,proc,sys,dev}
cp -r _install/* initramfs/

# 创建init脚本
cat > initramfs/init << 'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev
echo "=== RISC-V Linux Boot Successful ==="
echo "Welcome to QEMU RISC-V virt machine"
exec /bin/sh
EOF
chmod +x initramfs/init

# 打包initramfs
cd initramfs
find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz
cd ..

3. 启动QEMU

使用virt机器启动Linux:

qemu-system-riscv64 \
  -machine virt \
  -cpu rv64 \
  -smp 4 \
  -m 2G \
  -kernel /path/to/linux-6.6/arch/riscv/boot/Image \
  -initrd /path/to/initramfs.cpio.gz \
  -append "console=ttyS0 root=/dev/ram rdinit=/init" \
  -nographic

验证方法

启动后观察串口输出,预期看到以下关键信息:

Linux version 6.6.0 (user@host) (riscv64-linux-gnu-gcc-12 ...)
[    0.000000] Linux version 6.6.0 ...
[    0.000000] CPU: rv64
[    0.000000] Machine model: riscv-virtio,qemu
...
[    1.234567] Freeing unused kernel image (initmem) memory: 252K
[    1.234567] Run /init as init process
=== RISC-V Linux Boot Successful ===
Welcome to QEMU RISC-V virt machine
/ #

判定标准:

  1. 出现Machine model: riscv-virtio,qemu,确认virt机器被正确识别;
  2. 出现Run /init as init process,确认initramfs被正确加载;
  3. 出现/ #提示符,可输入命令(如uname -a、cat /proc/cpuinfo),确认Linux用户空间shell可用。
QEMU RISC-V Virt 机器启动流程 主机开发环境 Linux内核源码 make defconfig make -j$(nproc) BusyBox 静态编译 cpio打包 Image (内核) initramfs.cpio.gz qemu-system-riscv64 -machine virt -nographic 加载 QEMU virt机器 RISC-V 64 CPU rv64, SMP 4核 内存 (2GB) DDR4 模拟 UART串口 console=ttyS0 virtio总线 MMIO设备模拟 加载内核 → 解压 → 启动 输出 Guest Linux 内核初始化 setup_arch() 设备驱动 virtio-mmio initramfs挂载 root=/dev/ram 执行 /init 挂载proc/sys / # Shell 可交互 验证点:出现 "Machine model: riscv-virtio,qemu" → "Run /init as init process" → "/ #" 提示符

常见问题排查

现象可能原因解决方法
启动后无输出串口参数错误确认-append包含console=ttyS0
提示Kernel panic - not syncing: VFS: Unable to mount root fsinitramfs未正确加载检查-initrd路径,确认cpio.gz格式正确
编译内核时报binutils版本过旧交叉工具链版本低升级gcc-riscv64-linux-gnu至12.x以上
QEMU提示virt machine does not support this CPUCPU类型不匹配使用-cpu rv64或省略该参数

本案例通过QEMU的virt机器成功模拟RISC-V 64位处理器并启动Linux,验证了从内核编译、initramfs构建到QEMU启动的完整工具链。该环境可用于后续内核开发、驱动调试和系统级实验。