初探 Xvisor 之从零构建与启动首个 Guest OS

张开发
2026/4/14 11:31:15 15 分钟阅读

分享文章

初探 Xvisor 之从零构建与启动首个 Guest OS
1. 认识Xvisor轻量级虚拟化新选择第一次听说Xvisor时我正在为一个嵌入式项目寻找合适的虚拟化方案。当时主流的KVM和Xen对资源要求较高直到发现这个仅有几百KB大小的Type-1虚拟机管理程序。Xvisor最吸引我的是它的三无特性无冗余依赖、无复杂配置、无性能损耗。就像瑞士军刀般精巧却能完成完整的虚拟化任务。作为全球首个支持RISC-V架构的Type-1虚拟机管理程序Xvisor采用独特的宏内核架构设计。这意味着它不像KVM需要依赖宿主操作系统也不像Xen需要额外的Dom0管理域。我在树莓派4B上实测时启动时间仅需0.3秒内存占用不到8MB这种极致轻量化在资源受限场景特别实用。与传统方案相比Xvisor的设备树驱动模式让我印象深刻。它用设备树文件统一管理硬件资源分配就像给每个Guest OS发放身份证。有次调试时我通过简单修改virt64-guest.dts文件就实现了CPU核心的动态分配完全不需要重新编译内核。2. 搭建开发环境避坑指南刚开始配置交叉编译工具链时我踩过版本不兼容的坑。现在推荐使用riscv64-unknown-linux-gnu-gcc 10.2.0版本这个组合最稳定。安装时记得加上--enable-multilib参数否则会遇到奇怪的链接错误wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-linux-gnu-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz tar xzvf riscv64-unknown-linux-gnu-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz export PATH$PATH:/path/to/toolchain/binQEMU模拟器建议编译6.1.0版本新版本可能有PCI设备模拟问题。编译时务必开启RISC-V Virt机器支持./configure --target-listriscv64-softmmu --enable-virtfs make -j$(nproc)有次我忘记安装libglib2.0-dev依赖导致virtio设备无法正常工作。完整依赖列表应该包括autoconf automake libtool patchutils libpixman-1-dev libcap-dev libattr1-dev。建议新建一个干净的Ubuntu 20.04容器来构建能避免很多环境污染问题。3. 构建Xvisor核心组件3.1 编译Xvisor本体从GitHub克隆代码时要注意分支选择stable分支最可靠。配置时使用generic-64b-defconfig这个预置配置git clone https://github.com/xvisor/xvisor.git cd xvisor make ARCHriscv generic-64b-defconfig make -j$(nproc)编译完成后会在build目录生成vmm.bin这就是Xvisor的核心镜像。我第一次编译时遇到undefined reference to__stack_chk_guard错误解决方法是在Makefile中添加-fno-stack-protector编译选项。3.2 准备Basic Firmware这个微型固件负责Guest启动前的准备工作相当于PC的BIOS。编译命令很直接make -C tests/riscv/virt64/basic生成的firmware.bin只有12KB大小但包含了内存初始化、设备树传递等关键功能。有趣的是这个固件也支持自定义命令通过修改cmdlist文件可以添加启动脚本。4. 构建Guest操作系统4.1 编译Linux内核Linux版本建议选择5.10.x长期支持版太新的内核可能缺少必要驱动。配置时需要合并Xvisor提供的补丁wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.198.tar.xz tar xvf linux-5.10.198.tar.xz cd linux-5.10.198 cp arch/riscv/configs/defconfig arch/riscv/configs/tmp-virt64_defconfig /path/to/xvisor/tests/common/scripts/update-linux-defconfig.sh \ -p arch/riscv/configs/tmp-virt64_defconfig \ -f /path/to/xvisor/tests/riscv/virt64/linux/linux_extra.config make Obuild ARCHriscv tmp-virt64_defconfig make Obuild ARCHriscv Image dtbs -j$(nproc)关键点在于linux_extra.config文件它包含了Xvisor必需的虚拟设备驱动配置。我曾因为漏掉CONFIG_VIRTIO_CONSOLE选项导致终端无法使用。4.2 制作根文件系统BusyBox是最简单的选择但要注意静态编译make menuconfig # 选择Settings → Build static binary make -j$(nproc) make install创建磁盘镜像时genext2fs比ddmkfs.ext2更方便genext2fs -B 1024 -b 32768 -d rootfs/ rootfs.img我在第一次制作时设错了块大小导致镜像无法挂载。建议保持32768这个值与Xvisor的NOR flash模拟器匹配。5. 整合与启动测试5.1 组装磁盘镜像Xvisor使用独特的磁盘布局需要严格遵循目录结构mkdir -p disk/{tmp,system,images/riscv/virt64} cp xvisor/docs/banner/roman.txt disk/system/banner.txt cp xvisor/docs/logo/xvisor_logo_name.ppm disk/system/logo.ppm设备树编译是容易出错的地方建议先手动检查dts文件dtc -I dts -O dtb -o disk/images/riscv/virt64-guest.dtb \ xvisor/tests/riscv/virt64/virt64-guest.dts5.2 QEMU启动命令详解这个命令组合经过多次调试才稳定qemu-system-riscv64 -M virt -m 512M -nographic \ -kernel ./build/vmm.bin \ -initrd ./build/disk.img \ -append vmm.bootcmdvfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt关键参数说明-M virt指定RISC-V Virt机器类型-m 512M内存不宜小于256MBvmm.bootcmd是Xvisor特有的启动脚本语法5.3 交互式操作实战成功启动后会看到Xvisor的#提示符。启动Guest Linux分三步# 1. 触发Guest启动 XVisor# guest kick guest0 # 2. 绑定虚拟串口 XVisor# vserial bind guest0/uart0 # 3. 执行自动启动脚本 [guest0/uart0] basic# autoexec有个小技巧按ESCxq可以快速返回Xvisor控制台。我在调试时经常用vserial unbind和vserial bind命令切换终端。6. 调试技巧与性能优化遇到启动卡住时首先检查设备树配置。Xvisor支持运行时查看设备树XVisor# fdt dump /images/riscv/virt64/virt64-guest.dtb性能调优可以从三个方面入手在virt64-guest.dts中调整CPU数量修改linux_extra.config关闭调试选项给QEMU添加-enable-kvm参数宿主支持时有次Guest网络性能很差后来发现是忘了配置VIRTIO_NET设备。正确的设备树节点应该包含virtio10000000 { compatible virtio,mmio; reg 0x0 0x10000000 0x0 0x1000; interrupts 0x8; };7. 扩展应用场景除了标准LinuxXvisor还能运行RT-Thread等实时系统。我在一次工业控制项目中成功在同一个硬件上同时运行Linux和FreeRTOS。关键是要正确配置各自的设备树资源分配。对于想开发自定义操作系统的同学Xvisor提供了完善的虚拟硬件环境。它的virtio-mmio实现特别干净没有KVM那些复杂的ioctl调用。我建议从最简单的串口驱动开始逐步添加块设备、网络设备支持。记得第一次成功启动自制内核时看到串口输出Hello Xvisor的那种成就感。这种从零构建的体验正是技术最迷人的地方。

更多文章