前言
虚拟化技术发展了 20 多年,QEMU 作为标杆项目积累了数百万行 C 代码 —— 功能极致丰富,但代码体积、攻击面、内存安全 CVE 数量都让它在 Serverless、机密计算等新场景下显得「过重」。
在 QEMU 之外,三个轻量级 VMM 几乎同时崛起:AWS 的 Firecracker、Cloud Hypervisor、Google 的 crosvm。它们都用 Rust 写、都跑在 KVM 上、都瞄准「启动更快、内存更小、代码更精简」—— 但一个尴尬的事实是:这三个 VMM 把同一份基础代码独立写了三遍。KVM ioctl 封装、Guest 内存管理、virtqueue 实现、内核加载、事件循环 …… 每个项目都从零造了一遍轮子。每一行重复代码,都是一个潜在的内存漏洞入口。
2019 年由 Intel、Google、AWS、阿里云等多家厂商联合发起的 rust-vmm 项目,正是为了终结这种局面。它不是一款完整的 VMM,而是一套高度解耦、可按需组装的 Rust 虚拟化基础组件库 —— 把上述「重复造的轮子」沉淀为标准化、独立发布的 crate,让每个 VMM 项目专注于自己的差异化特性。
rust-vmm 遵循「一个组件一个 crate」的设计原则,所有 crate 独立发布、按需依赖,从最底层的系统调用封装到上层的设备模拟,覆盖了虚拟化技术栈的全部核心环节。本文将按功能分层,系统梳理 rust-vmm 生态下的全部核心 crate 及其定位、能力、核心 API 与最小调用示例,并在最后串出一个端到端的最小 VMM 实现。
核实声明:本文所有事实(仓库归属、架构支持、trait 名称、crate 是否存在、API 签名)均经过对 rust-vmm 组织 GitHub 仓库与 crates.io 的实际比对,更新于 2026-06;示例 API 以 docs.rs latest 为准。近一两年 rust-vmm 推动了多次「workspace 化合并」,部分原本独立的仓库(如
kvm-bindings、kvm-ioctls、vfio-user)已被归档并整合到 workspace 仓库中,下文会标注实际位置。
整体架构:分层解耦的虚拟化积木
rust-vmm 采用自底向上的分层设计,每一层只依赖下层能力,职责边界清晰:
graph TD
A[工程化与参考实现
rust-vmm-ci / rust-vmm-container / vmm-reference] --> B
B[启动与兼容层
linux-loader / vm-fdt / vm-superio / vm-superio-ser] --> C
C[硬件直通层
vfio-bindings / vfio-ioctls / vfio-user] --> D
D[VirtIO & vhost 半虚拟化层
virtio-bindings / virtio-queue / virtio-queue-ser / vhost / vhost-user-backend / vhost-device-*] --> E
E[核心资源层
vm-memory / vm-allocator / vm-device] --> F
F[Hypervisor 抽象层
kvm-bindings / kvm-ioctls / mshv-bindings / mshv-ioctls] --> G
G[基础系统工具层
vmm-sys-util / event-manager]
基础系统工具层
这一层是整个 rust-vmm 生态的公共基座,将操作系统底层能力封装为安全、跨平台的 Rust 接口。
vmm-sys-util
- GitHub:https://github.com/rust-vmm/vmm-sys-util
- crates.io:https://crates.io/crates/vmm-sys-util
- 平台支持:Linux(完整)/ Windows(部分支持)
- 架构支持:x86_64 / aarch64 / riscv64
所有 rust-vmm 组件最核心的公共依赖。它将 eventfd、ioctl、epoll、文件描述符管理、tempfile、字节序处理、errno 错误类型、灵活数组成员(FAM)安全封装等系统级原语统一收敛在一个 crate 中,把 unsafe 收拢到最小范围。
核心 API:eventfd::EventFd、ioctl_*! 宏家族(ioctl_none! / ioctl_io! / ioctl_ior! / ioctl_iow! / ioctl_iowr!)、ioctl_with_val / ioctl_with_ref、tempfile::TempFile、epoll、errno::Error、fam::FamStruct。
最小示例(来自源码 doctest):
1 | use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK}; |
EventFd 在 rust-vmm 里被广泛用作中断注入信号、退出信号、跨线程唤醒的轻量通道。
event-manager
- GitHub:https://github.com/rust-vmm/event-manager
- crates.io:https://crates.io/crates/event-manager
- 平台支持:仅 Linux(基于 epoll)
轻量级事件驱动框架,VMM 中 I/O 事件、中断事件的核心调度器。它采用「事件管理器 - 事件订阅者」模型,提供两种订阅 trait 适配不同借用语义场景:
EventSubscriber:要求&self,适用于通过Arc<T>共享、内部用Mutex自管的场景MutEventSubscriber:要求&mut self,适用于经Mutex<T>/RefCell<T>包装后由 manager 独占借用的场景
核心 API:EventManager<T>、EventSubscriber / MutEventSubscriber、EventOps、Events、SubscriberId、SubscriberOps。
最小示例:
1 | use event_manager::{EventManager, EventOps, Events, MutEventSubscriber}; |
init 中注册感兴趣的 fd,process 中处理就绪事件;VMM 在主循环里反复调用 EventManager::run。
Hypervisor 抽象层
这一层直接对接操作系统内核的虚拟化模块,将底层 unsafe 的内核接口封装为类型安全的 Rust API。rust-vmm 同时支持 Linux KVM 与微软 MSHV 两大虚拟化平台。
KVM 系列:Linux 硬件虚拟化标准接口
自 2024 年起,原
rust-vmm/kvm-bindings与rust-vmm/kvm-ioctls已归档合并至单仓库 https://github.com/rust-vmm/kvm(workspace),但 crates.io 上的两个 crate 名称与发布节奏不变。
kvm-bindings
- GitHub:https://github.com/rust-vmm/kvm(原 https://github.com/rust-vmm/kvm-bindings 已归档)
- crates.io:https://crates.io/crates/kvm-bindings
- 架构支持:x86_64 / aarch64 / riscv64(三架构均已稳定支持)
通过 bindgen 自动生成的 Linux KVM API 原生 FFI 绑定,包含所有 KVM ioctl 命令、数据结构与常量定义,并为灵活数组成员(如 kvm_cpuid2、kvm_msr_list)提供安全的 FAM 封装,是 Rust 代码与 KVM 内核交互的底层协议基础。
kvm-ioctls
- GitHub:https://github.com/rust-vmm/kvm(原 https://github.com/rust-vmm/kvm-ioctls 已归档)
- crates.io:https://crates.io/crates/kvm-ioctls
- 架构支持:x86_64 / aarch64 / riscv64
构建在 kvm-bindings 之上的安全封装层,将原本 unsafe 的 ioctl 调用转化为类型安全的高级 API。
C vs Rust 风格对比 —— 同样的「打开 KVM、创建 VM、注册 Guest 内存」三步,C 与 Rust 的差异:
1 | // C 语言:手动管理 fd、手填结构体、逐个检查返回值 |
1 | // Rust:fd 由所有权管理、Result 强制错误处理;unsafe 仅围在内存注册一处 |
差异不在于「行数少了几行」,而在于:错误必须显式处理(? 编译期强制),文件描述符与所有权绑定(不会泄漏 / 重复关闭),类型由编译器检查(不会把 vm_fd 误传给 Kvm 系统级 ioctl)。unsafe 被收缩到唯一一处真正越过 Rust 安全边界的调用上 —— 这就是「最小 unsafe 表面积」原则。
核心 API:
Kvm:系统级 ioctl 入口(new、create_vm、get_api_version、check_extension)VmFd:VM 级(set_user_memory_region、create_vcpu、get_dirty_log、create_irq_chip、register_irqfd)VcpuFd:vCPU 级(get_regs/set_regs、get_sregs/set_sregs、run)VcpuExit:枚举Hlt/IoIn/IoOut/MmioRead/MmioWrite/ …
最小示例(节选自 kvm-ioctls 顶层 doctest,x86_64):
1 | use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; |
经典的「五步走」流程:Kvm::new → create_vm → set_user_memory_region → create_vcpu 并 setup regs → vcpu.run() 循环匹配 VcpuExit。
MSHV 系列:Windows 平台虚拟化支持
mshv-bindings / mshv-ioctls
- GitHub:https://github.com/rust-vmm/mshv(同一 workspace 包含两个 crate)
- crates.io:https://crates.io/crates/mshv-bindings、https://crates.io/crates/mshv-ioctls
- 架构支持:官方 README 声明 x86_64;arm64 绑定文件已生成、支持正在演进中(尚未列为 Supported Platform)
对应微软 Hypervisor(MSHV)的 FFI 绑定与安全接口封装,让 rust-vmm 突破 Linux 限制,可适配 Azure 等 Windows 云环境。设计逻辑与 KVM 系列完全一致(Mshv / VmFd / VcpuFd),降低跨平台开发的心智负担。
虚拟机核心资源层
这一层定义了虚拟机的核心资源模型 —— 内存、地址空间、设备抽象,是所有虚拟设备与业务逻辑的运行载体。
vm-memory
- GitHub:https://github.com/rust-vmm/vm-memory
- crates.io:https://crates.io/crates/vm-memory
- 架构支持:x86_64 / aarch64 / riscv64;OS:Linux/Unix/Windows;可选
xenfeature(仅 Unix)
虚拟机客户机内存管理的基石组件。它支持匿名内存、文件 - backed 内存的 mmap 映射,实现了客户机物理地址(GPA)到宿主机虚拟地址(HVA)的安全转换,提供脏页跟踪、原子读写、零拷贝数据传输、跨字节序访问等核心能力,是设备 DMA 模拟、虚拟机热迁移、内存快照的基础支撑。
核心 API:
- trait:
GuestMemory(只读视图)、GuestMemoryRegion、Bytes(read/write/read_obj/write_obj)、Address - 类型:
GuestAddress、GuestUsize、GuestMemoryMmap<B = ()>、MmapRegion、GuestRegionMmap、GuestMemoryAtomic(多线程换页 / 快照)
最小示例(来自 README):
1 | use vm_memory::{Bytes, GuestAddress, GuestMemoryMmap}; |
GuestMemoryMmap::from_ranges 在宿主匿名 mmap 出来的内存基础上构建 guest 物理地址空间;Bytes trait 让设备模型直接以 (addr, slice) 方式跨 region 读写。
vm-allocator
虚拟机系统资源分配器,负责 MMIO 地址空间、PIO 端口、中断号(GSI)、设备 ID 等硬件资源的分配与回收。它支持地址区间对齐校验、资源冲突检测,确保虚拟机的硬件资源布局符合架构规范。
核心 API:
IdAllocator:整数资源分配器(如 GSI、KVM memslot id),用BTreeSet维护已释放 IDAddressAllocator:区间资源分配器(基于 IntervalTree 的地址段)AllocPolicy::{FirstMatch, LastMatch, ExactMatch}、Constraint、RangeInclusive
最小示例:
1 | use vm_allocator::{AddressAllocator, AllocPolicy, IdAllocator}; |
vm-device
虚拟设备的统一抽象框架。它定义了 PIO 与 MMIO 两条总线上的设备 trait,并提供 IoManager 作为按地址段路由 I/O 的总线分发器。所有虚拟设备均可基于这套抽象开发,无缝接入任意 VMM。
核心 API:
- 设备 trait(共 4 个):
- PIO:
DevicePio(不可变 self)、MutDevicePio(可变 self) - MMIO:
DeviceMmio(不可变 self)、MutDeviceMmio(可变 self)
- PIO:
- 总线 trait:
PioManager、MmioManager - 具体管理器:
IoManager - 地址类型:
PioAddress、PioRange、MmioAddress、MmioRange
最小示例(来自 README):
1 | use std::sync::{Arc, Mutex}; |
VMM 在 VcpuExit::IoOut/MmioWrite 上调用 mgr.pio_write/mmio_write,Manager 按地址范围找到对应设备并转发。
VirtIO 生态层
VirtIO 是云计算领域的事实半虚拟化设备标准,rust-vmm 提供了从协议绑定到队列实现、再到设备框架的完整支持。
仓库结构:
virtio-bindings、virtio-queue、virtio-queue-ser、virtio-blk、virtio-console、virtio-device、virtio-vsock等 crate 同属一个仓库 https://github.com/rust-vmm/vm-virtio(workspace),并非各自独立仓库,且 crates.io 上没有名为vm-virtio的 crate,仓库名只是 workspace 容器。
virtio-bindings
- GitHub:https://github.com/rust-vmm/vm-virtio(子 crate
virtio-bindings/) - crates.io:https://crates.io/crates/virtio-bindings
VirtIO 规范的原生 FFI 绑定(来源是 Linux kernel 的 virtio uapi 头文件),定义了 VirtIO 设备的标准数据结构、特性位、队列协议常量,按内核版本提供不同 feature。是所有 VirtIO 相关组件的协议底座。
virtio-queue
- GitHub:https://github.com/rust-vmm/vm-virtio(子 crate
virtio-queue/) - crates.io:https://crates.io/crates/virtio-queue
VirtIO Split Virtqueue 的纯 Rust 完整实现,包含描述符表、可用环(avail ring)、使用环(used ring)的全部逻辑,并通过 Kani 进行了形式化证明。
Split Virtqueue 由三段共享内存组成,driver(Guest)与 device(VMM)分别担任生产者与消费者:
1 | ┌────────────────────── Guest 物理内存(共享) ──────────────────────┐ |
数据流:driver 把缓冲区地址填进 Descriptor Table,把 chain 头索引推到 Avail Ring 并踢一脚(通常通过 PCI/MMIO 写);device 通过 iter() 从 Avail Ring 拉出 DescriptorChain,处理完后用 add_used 把结果放回 Used Ring,再按 needs_notification 决定是否注入中断。
virtio-queue 把这三块结构封装为线程安全的 Rust 对象,并把所有「描述符链解析、回绕、内存屏障」之类的细节正确性问题做掉了 —— 这部分代码经过 Firecracker / Cloud Hypervisor / crosvm 三大 VMM 的生产验证,远比每个项目各自实现可靠。
核心 API:
Queue(单线程)、QueueSync(Arc<Mutex<Queue>>)- trait:
QueueT/QueueOwnedT Descriptor、DescriptorChain、DescriptorChainRwIter、AvailIterQueueState(save/restore 用)
最小示例(节选自 Queue doctest):
1 | use virtio_queue::{Queue, QueueOwnedT, QueueT}; |
标准的 split virtqueue 处理循环 —— 禁用通知 → 迭代 AvailIter 取出 DescriptorChain → 处理后 add_used → 按 needs_notification 决定是否触发中断。
virtio-queue-ser
- GitHub:https://github.com/rust-vmm/vm-virtio(子 crate
virtio-queue-ser/) - crates.io:https://crates.io/crates/virtio-queue-ser
virtio-queue 的版本感知序列化扩展,对 QueueState 进行序列化与反序列化。它是热迁移的关键 —— 虚拟机暂停后,可将所有 VirtIO 设备的队列状态持久化,目标主机恢复后重建队列状态,保证业务无感知迁移。
vhost 与 vhost-user 层
vhost 系列组件将 VirtIO 设备的数据面从 VMM 进程中剥离,分别下沉到内核态(vhost)、独立用户态进程(vhost-user)或硬件(vDPA),既提升性能,又通过进程隔离缩小攻击面。
vhost
- GitHub:https://github.com/rust-vmm/vhost(workspace,同时包含
vhost-user-backend) - crates.io:https://crates.io/crates/vhost
vhost、vhost-user、vDPA 三种加速方案的统一抽象库。它屏蔽了内核态 vhost、用户态 vhost-user、硬件 vDPA 的实现差异,提供统一的 vring 操作、事件通知、特性协商接口。
vhost-user-backend
- GitHub:https://github.com/rust-vmm/vhost(与
vhostcrate 同 workspace 子 crate) - crates.io:https://crates.io/crates/vhost-user-backend
vhost-user 后端设备的通用开发框架,完整封装了 vhost-user 协议的控制面交互逻辑:握手、特性协商、队列配置、生命周期管理、中断注入。开发者只需实现设备的数据面处理逻辑。
核心 API:
- trait:
VhostUserBackend/VhostUserBackendMut(num_queues、max_queue_size、features、set_event_idx、update_memory、handle_event、process_queue等) VhostUserDaemon<S, V, B>:服务端入口(new/start/wait/get_epoll_handlers)- vring trait:
VringT,三种实现VringState/VringMutex/VringRwLock
最小示例(来自 README,关键骨架;下面的 Error::* 为读者自定义错误类型,需结合具体后端实现):
1 | use vhost_user_backend::{VhostUserBackendMut, VringMutex, VringT}; |
vhost-device 系列
- GitHub:https://github.com/rust-vmm/vhost-device(workspace)
rust-vmm 社区维护的开箱即用 vhost-user 设备集合,每个设备是 workspace 内独立的二进制 crate(vhost-device-<name>)。截至 2026-06,仓库内官方设备清单(按字母序):
| crate | 用途 | crates.io |
|---|---|---|
vhost-device-can |
CAN 总线(车载 / 工控) | https://crates.io/crates/vhost-device-can |
vhost-device-console |
串口 / 控制台 | https://crates.io/crates/vhost-device-console |
vhost-device-gpio |
GPIO | https://crates.io/crates/vhost-device-gpio |
vhost-device-gpu |
GPU(virtio-gpu) | https://crates.io/crates/vhost-device-gpu |
vhost-device-i2c |
I2C 总线 | https://crates.io/crates/vhost-device-i2c |
vhost-device-input |
输入设备(键鼠等) | https://crates.io/crates/vhost-device-input |
vhost-device-rng |
熵源 / 随机数 | https://crates.io/crates/vhost-device-rng |
vhost-device-scmi |
ARM SCMI 协议 | https://crates.io/crates/vhost-device-scmi |
vhost-device-scsi |
SCSI 块存储 | https://crates.io/crates/vhost-device-scsi |
vhost-device-sound |
音频(virtio-snd) | https://crates.io/crates/vhost-device-sound |
vhost-device-spi |
SPI 总线 | https://crates.io/crates/vhost-device-spi |
vhost-device-vsock |
guest-host socket 通道 | https://crates.io/crates/vhost-device-vsock |
vhost-device-template |
新设备开发模板 | — |
vhost-device-video(staging) |
视频编解码 | — |
辨析:
vhost-device-blk、vhost-device-net并不存在于本仓库。块设备 / 网络设备的 vhost-user 实现一般由 VMM 自带(如 Cloud Hypervisor 的vhost-user-block、SPDK 的vhost-user-blk、DPDK 的vhost-user-net)或者部署内核态 vhost-net。
VFIO 硬件直通层
对于需要极致性能的场景(如 GPU 计算、高速网卡),rust-vmm 提供了完整的 VFIO 硬件直通支持。
原
rust-vmm/vfio-user已于 2025 年归档,源码迁移至 https://github.com/rust-vmm/vfio workspace;vfio-bindings、vfio-ioctls、vfio-user三个 crate 现位于同一仓库。
vfio-bindings
- GitHub:https://github.com/rust-vmm/vfio(子 crate
vfio-bindings/) - crates.io:https://crates.io/crates/vfio-bindings
Linux VFIO(Virtual Function I/O)子系统的 FFI 绑定,包含 VFIO 容器、设备组、物理设备的所有数据结构与 ioctl 命令定义。
vfio-ioctls
- GitHub:https://github.com/rust-vmm/vfio(子 crate
vfio-ioctls/) - crates.io:https://crates.io/crates/vfio-ioctls
- 平台支持:Linux;x86_64 主测,aarch64 支持中(依赖 ARM SMMU)
VFIO API 的安全 Rust 封装,支持 PCIe 设备的完整透传流程。
核心 API:
VfioContainer:包装/dev/vfio/vfio,提供vfio_dma_map/vfio_dma_unmapVfioDevice:单个透传设备(get_irq_info、enable_irq、region_read/region_write、get_region_info)VfioGroup、VfioRegion、VfioIrq、错误类型VfioError
最小骨架(仓库未提供独立 examples,下面按公共 API 还原):
1 | use std::path::Path; |
vfio-user
- GitHub:https://github.com/rust-vmm/vfio(子 crate
vfio-user/,原独立仓库rust-vmm/vfio-user已于 2025-05 归档) - crates.io:https://crates.io/crates/vfio-user
vfio-user 协议(基于 Nutanix libvfio-user 规范)的纯 Rust 实现,同时提供 Client(VMM 侧)与 Server(设备侧)两种 struct,支持把物理 / 模拟设备以 socket 形式远程挂载到虚拟机,适合分布式虚拟化与设备池化。
关于 iommufd:截至 2026-06,rust-vmm 组织下并不存在
iommufd-bindings或iommufd-ioctls这两个 crate。Linux 新一代 iommufd 子系统的能力目前通过vfio-bindings/vfio-ioctls在 VFIO 容器/IOMMUFD 兼容路径中暴露;如未来 rust-vmm 推出独立的 iommufd crate,会以 workspace 子 crate 形式发布在 vfio 仓库。本节不再假装存在这两个 crate。
启动与兼容层
这一层提供虚拟机启动所需的内核加载、硬件信息传递、legacy 设备兼容能力,是 Guest OS 正常引导的基础。
vm-superio / vm-superio-ser
- GitHub:https://github.com/rust-vmm/vm-superio(workspace,包含两个 crate)
- crates.io:https://crates.io/crates/vm-superio、https://crates.io/crates/vm-superio-ser
经典超级 I/O 控制器的模拟实现,包含:
Serial<T, EV, W>:16550A UART 串口(PC 与多数嵌入式平台通用)Rtc<EV>:ARM PL031 RTC(注意是 ARM 的 PL031,不是 PC 上的 CMOS RTC,也不是 i8042)I8042Device:极简 i8042 PS/2 控制器,目前仅模拟 CPU Reset 命令用于关机通告
vm-superio-ser 提供配套的 *StateSer 序列化结构,支持热迁移时 legacy 设备状态的 save/restore。
最小示例(16550A UART):
1 | use std::io::{Error, Result}; |
最小示例(PL031 RTC):
1 | use std::time::{SystemTime, UNIX_EPOCH}; |
linux-loader
- GitHub:https://github.com/rust-vmm/linux-loader
- crates.io:https://crates.io/crates/linux-loader
- 架构支持:x86_64 / aarch64 / riscv64
Linux 内核加载器,按架构提供不同的具体实现:
| Loader | feature | 适用范围 |
|---|---|---|
loader::elf::Elf |
elf |
x86_64:同时承担 Linux 64-bit boot protocol 与 PVH boot protocol,PVH 入口由 ELF Note 发现,编码在结果的 pvh_boot_cap 字段 |
loader::bzimage::BzImage |
bzimage |
x86_64:传统 bzImage |
loader::pe::PE |
pe |
aarch64 / riscv64:内核 Image(PE/COFF 格式) |
注意:
PVH不是独立 loader,而是Elfloader 通过KernelLoaderResult::pvh_boot_cap暴露的能力。
核心 API:trait KernelLoader::load、返回值 KernelLoaderResult(kernel_load、kernel_end、setup_header、pvh_boot_cap)、独立函数 load_cmdline、命令行构造器 Cmdline。
最小示例(节选自 README,bzImage):
1 | use std::fs::File; |
vm-fdt
- GitHub:https://github.com/rust-vmm/vm-fdt
- crates.io:https://crates.io/crates/vm-fdt
- 维护状态:低频维护中,最近发布 v0.3.0(2023-11,支持
no_std);最近一次提交 2024-04,未弃用
扁平化设备树(FDT/DTB)生成库,符合 Devicetree Specification 规范。在 aarch64、riscv64 等架构下,它负责向 Guest OS 传递硬件拓扑、内存布局、中断控制器、设备地址等启动信息。
核心 API:FdtWriter(new / begin_node / end_node / finish)、节点句柄 FdtWriterNode、属性 setter(property_string / property_u32 / property_u64 / property_array_u32 / property_array_u64 / property_null / property_string_list / 裸字节 property)。
最小示例(来自 README):
1 | use vm_fdt::{Error, FdtWriter}; |
工程化与参考实现
本节的三个项目都不是 crate(crates.io 上未发布),而是配套基础设施仓库。
rust-vmm-ci
社区统一的 CI 测试框架(Buildkite pipeline + pytest),通过 git submodule 引入到各 rust-vmm 仓库,提供一致的单元测试、格式检查(rustfmt)、Clippy、依赖漏洞审计、覆盖率检查。
rust-vmm-container
预配置的开发测试 Docker 镜像(rustvmm/dev),内置 Rust 工具链、x86_64 / aarch64 / riscv64 平台的内核头文件、QEMU 测试工具、依赖库等,让开发者一键搭建一致的 rust-vmm 开发与测试环境。
vmm-reference
官方参考 VMM 实现,通过极少量胶水代码串联起核心 rust-vmm 组件,构建出一个可直接运行的最小功能虚拟机。注意它声明为「实验性」、不应用于生产,定位是学习 / 验证 / 二次开发的范本。
端到端实战:用 rust-vmm 串一个最小 VMM
理解了各 crate 之后,我们用一段精简代码把 kvm-ioctls + vm-memory + linux-loader + event-manager + vm-device 串起来,看一个最小 VMM 在控制流上是什么样子。
声明:以下是概念性骨架,目的在于展示 API 拼装方式与控制流,省略了真正启动 Linux 所需的若干细节(boot params zero-page、CPUID/MSR、IDT、页表、APIC/GIC、ACPI/FDT、MPTABLE 等架构相关初始化)。要跑起一个真实 Linux Guest,请直接参考
vmm-reference。
整体架构
一个生产级 VMM 通常由 API 线程 + 多个 vCPU 线程 + 一个事件循环线程 组成:
1 | ┌─────────────────────────────────────────────────────────────┐ |
最小骨架代码
1 | use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; |
回顾这段代码的关键节点:
| 步骤 | 涉及 crate | 干了什么 |
|---|---|---|
| 1 | kvm-ioctls |
打开 /dev/kvm、KVM_CREATE_VM,得到 VM 句柄 |
| 2 | vm-memory |
在宿主匿名 mmap 上构建 GPA 到 HVA 的安全映射 |
| 3 | kvm-ioctls + kvm-bindings |
KVM_SET_USER_MEMORY_REGION 把宿主内存注册为 memslot |
| 4 | linux-loader |
解析内核格式、写入 Guest 内存、返回入口地址 |
| 5 | kvm-ioctls |
创建 vCPU 并设置寄存器(这里大幅简化) |
| 6 | kvm-ioctls + vm-device |
vcpu.run() 进入 KVM;VM-Exit 上分派给 IoManager |
真实 VMM 还要做什么:在第 6 步之外,还有一个独立的 event-manager 线程跑 epoll,处理 virtio 设备的 eventfd notification、串口输入、API 请求 → 把消息塞进对应设备的 process_queue,再通过 irqfd 注入中断给 vCPU。这个事件循环 + vCPU 线程 + IoManager 三者协作的图景,就是上面架构图里展示的内容。
如果要看这段骨架完整跑起来的版本,最好的范本就是 vmm-reference:它在不到 5 千行 Rust 代码里串联了几乎所有 rust-vmm 组件,是「活文档」级别的学习材料。
生态落地:三大 Rust VMM 一览
rust-vmm 的价值最终体现在它被多个生产级 VMM 实际复用上。下面看三大 VMM 各自的差异化策略。
Firecracker(AWS)
Firecracker 是 rust-vmm 最早的采用者之一,定位 Serverless/FaaS,设计哲学是「做减法」:
- 只支持 KVM、x86_64 / aarch64
- 仅实现 Serverless 场景必需的设备(VirtIO-net / VirtIO-blk / Serial / vsock 等),无 PCI 总线(仅使用 VirtIO-MMIO)
- 自带 Jailer 安全沙箱:
pivot_root文件系统隔离 + seccomp 三线程独立 filter + cgroups 资源限制 + setuid 降权 - 支持微快照与按需分页(基于
userfaultfd),冷启动可降至毫秒级
主要复用的 rust-vmm crate:kvm-ioctls、vm-memory、vmm-sys-util、virtio-queue、linux-loader、vm-superio、event-manager。
Cloud Hypervisor(Linux Foundation)
Cloud Hypervisor 最初由 Intel 发起,现由 Linux Foundation 社区维护,定位 通用云虚拟机,设计哲学是「做加法」:
- 同时支持 KVM 与 MSHV(通过其内置的
hypervisor抽象 crate 切换;该 crate 属于 Cloud Hypervisor 项目,不在 rust-vmm 组织下) - 使用 VirtIO-PCI 而非 VirtIO-MMIO,配合 ACPI 设备发现,对 Windows Guest 友好
- 设备模型丰富:virtio-gpu、virtio-fs、vhost-user 后端、热插拔
- 支持机密计算(Intel TDX、AMD SEV/SEV-SNP)、VFIO 直通
几乎覆盖 rust-vmm 全部组件,是 Kata Containers 的主流后端之一。
crosvm(Google)
crosvm 是 Google 为 ChromeOS、Android 打造的 VMM,也是 rust-vmm 多个组件的重要上游贡献者。它的杀手锏是 每设备独立沙箱进程:
1 | crosvm 主进程(最小权限) |
ChromeOS 的运行环境天然是不可信用户(浏览器)—— 即使某个设备模拟存在漏洞被攻破,攻击者也只能拿到一个权限极度受限的子进程。这种「VMM 内部纵深防御」比 Firecracker 的 Jailer 更进一步。
三大 VMM 对比
| 维度 | Firecracker | Cloud Hypervisor | crosvm |
|---|---|---|---|
| 背后 | AWS | Linux Foundation | |
| 哲学 | 极简 | 完备 | 纵深隔离 |
| 设备总线 | VirtIO-MMIO | VirtIO-PCI | VirtIO-MMIO + PCI |
| Hypervisor | KVM | KVM + MSHV | KVM |
| Guest OS | Linux | Linux + Windows | Linux + Android |
| 沙箱模型 | Jailer 多层防御 | 无内置(部署侧自行沙箱) | 每设备独立进程 |
| 杀手锏 | 微快照 + CPU Template | 热插拔 + 机密计算 | 设备级沙箱 |
| 典型场景 | Serverless / FaaS | 通用云 / Kata | ChromeOS / Android |
国内生态中,Dragonball(蚂蚁/阿里、Kata 内置 VMM)与 StratoVirt(华为 openEuler,覆盖云、边缘、嵌入式)也都基于 rust-vmm 构建。
为什么不统一成一个 VMM?
读完上面的对比,自然会问:既然都用 rust-vmm,为什么不直接维护一个统一的 VMM?
答案是 —— 不同场景对 VMM 的需求天然冲突:
- AWS Lambda:极致冷启动(毫秒级)、最小内存开销(几 MB)、只跑 Linux、不需要 PCI / GPU / USB → 要的是「减法」
- Cloud Hypervisor:支持 Windows、PCI 设备、热插拔、多 Hypervisor 后端、接近通用虚拟机的功能完备性 → 要的是「加法」
- crosvm:每个设备独立沙箱进程、ChromeOS / Android 深度集成、virtio-gpu 图形加速 → 要的是「隔离」
减法、加法、隔离 —— 这三者在架构层面就是矛盾的。试图用一个 VMM 满足所有场景,结果必然是代码膨胀、性能妥协、安全模型妥协。rust-vmm 的设计智慧正在于此:共享基础设施(KVM 封装、内存管理、virtqueue),但不共享产品本身。每个 VMM 在自己的场景里做到极致,同时从共享组件中受益。
安全:Rust 改变游戏规则
如果说 rust-vmm 解决了「重复造轮子」的效率问题,那么 Rust 语言本身就解决了虚拟化领域最大的痛点 —— 内存安全。
Rust 编译期消灭的几类漏洞
QEMU 历史上的内存安全 CVE 几乎全部是 C 语言的固有顽疾:
| 漏洞类别(CWE) | C 中的常见成因 | Rust 编译期保证 |
|---|---|---|
| 缓冲区溢出(CWE-119/787) | 手动越界写 | 数组/切片下标编译期或运行时检查 |
| 空指针解引用(CWE-476) | NULL 检查遗漏 |
Option<T> 强制模式匹配,引用永远非空 |
| Use-After-Free(CWE-416) | 释放后继续访问 | 借用检查器 + 生命周期保证 |
| Double Free(CWE-415) | 重复 free |
所有权移动,单一所有者 drop |
| 数据竞争(CWE-362) | 多线程裸共享 | Send / Sync trait 编译期约束 |
Guest VM 本身就是潜在的恶意环境 —— 它能通过 MMIO / PIO / virtqueue 触发 VMM 中的任何代码路径。用 C 写 VMM 像在不设防的城市里巡逻;用 Rust 写至少城墙是坚固的。
不是「零 CVE」,是「显著降维」
⚠️ 请避免被「Rust VMM 零 CVE」的说法误导。 Firecracker / Cloud Hypervisor / crosvm 历史上都披露过 CVE,只是相比 QEMU 的 CWE-119 系列内存破坏类漏洞,Rust VMM 中典型 C 类内存安全问题显著减少。仍然存在的风险包括:
unsafe块中的 bug:FFI、裸指针操作(如set_user_memory_region)依然可能引入 UAF / 越界,需要额外审计- 逻辑漏洞:权限校验缺失、状态机错误、整数溢出语义错误 —— 这些 Rust 不管
- 侧信道 / DoS:如 vCPU 资源耗尽、虚假中断风暴
- 依赖链供应链攻击:Cargo.lock 锁版本可降低但不能消除
真正的安全收益是「攻击面降维」—— 把绝大多数低成本、易批量化的内存破坏 bug 在编译期消灭,让审计与 fuzzing 可以聚焦在更窄的
unsafe表面与逻辑层面。
rust-vmm 的额外安全实践
- 每个 crate 经过社区与安全专家共同的代码审计
- 共享 CI(
rust-vmm-ci)统一跑 Clippy、cargo audit、fuzzing - 关键组件(如
virtio-queue)用 Kani 做形式化证明 unsafe块通常被收拢到vmm-sys-util、*-bindings、*-ioctls等少数 crate 中,便于集中审计
总结
回顾 VMM 的二十年演进:
1 | 2000s ── QEMU |
rust-vmm 最深刻的意义不在某个 crate 写得多好,而在于它改变了虚拟化领域的协作模式 —— AWS、Intel、Google 这三家在云市场上短兵相接的对手,选择在 VMM 基础设施层面携手合作。这不是慈善,而是工程理性的胜利:当底层代码的安全性与正确性可以被共享验证,每一个参与者都受益。
「基础共享、上层竞争」的模式正在产生实实在在的成果:
- Firecracker 让 AWS Lambda 的冷启动从秒级降至毫秒级
- Cloud Hypervisor 让 Windows VM 在 KVM/MSHV 上同样高效,并打通 TDX/SEV 机密计算路径
- crosvm 把 ChromeOS 的安全模型从浏览器延伸到了虚拟机
- Dragonball / StratoVirt 让国内云厂商在容器与边缘场景拿到自主可控的轻量 VMM
随着云原生与安全需求的持续升级,rust-vmm 生态仍在不断扩展 —— RISC-V 架构(KVM / linux-loader / vm-memory 已稳定支持)、机密计算(TDX / SEV / SEV-SNP / pKVM)、更多设备模型(sound、video、scmi)都在持续推进。它不仅是 Rust 语言在系统级领域的标杆项目,更是下一代云基础设施的重要技术基石。
虚拟化的下一个十年,属于 Rust。
参考链接
- rust-vmm 组织主页:https://github.com/rust-vmm
- rust-vmm community(贡献规范、crate 治理):https://github.com/rust-vmm/community
- rust-vmm monorepo(集中后的工具仓库):https://github.com/rust-vmm/rust-vmm
- crates.io 关键字搜索:https://crates.io/search?q=rust-vmm


