4. 虚拟化基础概念
虚拟化并不是“把一台机器切成几台”这么简单,它本质上是在硬件与操作系统之间插入一层抽象,让多个执行环境共享同一套物理资源,同时彼此看起来像独占机器。理解虚拟化,需要抓住四个关键词:VMM 类型、全虚拟化与半虚拟化、硬件辅助虚拟化、隔离与资源抽象。在 RISC-V 场景下,这四者共同决定了 Hypervisor 的设计方式与 Guest OS 的改造程度。
一、虚拟机监控器(VMM/Hypervisor)的两种类型
虚拟机监控器负责创建、调度和隔离虚拟机。按它与硬件的相对位置,通常分为 Type-1 与 Type-2。
- Type-1(裸机型):Hypervisor 直接运行在硬件之上,如 Xen、KVM 在宿主内核中承担虚拟化职责、RISC-V 上的 Bao、Xvisor。它控制中断、内存和 CPU 时间,Guest OS 运行在其上层,性能与隔离性更接近生产环境。
- Type-2(宿主型):Hypervisor 作为宿主操作系统上的一个应用或内核模块运行,如 VirtualBox、VMware Workstation。部署方便,但路径更长,I/O 与中断延迟通常更高。
在 RISC-V 中,Type-1 常与 M 模式固件、S 模式 Hypervisor 扩展配合:M 模式负责平台初始化与安全监控,S 模式 Hypervisor 通过 hstatus、hedeleg、hvip 等 CSR 管理 Guest 的异常与中断。Type-2 则更多用于开发调试和教学验证。
二、全虚拟化与半虚拟化
全虚拟化追求“Guest 无需修改”。Hypervisor 通过模拟特权指令、影子页表或二级页表,让未修改的 Guest OS 以为自己运行在真实硬件上。半虚拟化则要求 Guest 感知虚拟化环境,主动使用 Hypercall、共享环等接口与 Hypervisor 协作,以换取更低的陷入开销。
| 对比维度 | 全虚拟化 | 半虚拟化 |
|---|---|---|
| Guest 修改 | 不需要 | 需要适配前端驱动或 Hypercall |
| 典型陷入来源 | 特权指令、MMIO、页表 | 显式 Hypercall、事件通道 |
| 性能 | 依赖硬件辅助,否则开销大 | I/O 与调度路径更短 |
| 兼容性 | 强,可运行闭源系统 | 弱,需 Guest 配合 |
| RISC-V 场景 | 依赖 H 扩展与二级页表 | 常用于 virtio 前端驱动 |
实际系统往往混合使用:CPU 与内存走全虚拟化路径,I/O 走半虚拟化路径。例如 Guest 中的 virtio-blk 前端把请求放入共享环,后端由 Hypervisor 或宿主内核完成真实块设备访问,从而避免逐字节模拟磁盘控制器。
三、硬件辅助虚拟化:把“陷入”交给硬件
没有硬件辅助时,Hypervisor 必须扫描或改写 Guest 页表,并捕获所有敏感指令,开销高且实现复杂。RISC-V 的 H 扩展提供了关键支撑:
- 两级地址翻译:Guest 虚拟地址先经 VS 模式页表翻译成 Guest 物理地址,再经 HS 模式页表翻译成宿主物理地址,由硬件完成,减少软件影子页表维护。
- 虚拟化 CSR:
hstatus、hedeleg、hideleg、hvip、hgatp等让 Hypervisor 精确控制异常委托与中断注入。 - 陷入与恢复:Guest 执行
ecall或触发异常时,硬件切换到 HS 模式,Hypervisor 处理后通过sret返回 Guest。
# 典型 RISC-V Hypervisor 启动片段(示意)
# 设置 Guest 物理地址翻译基址
csrw hgatp, t0
# 委托部分异常给 VS 模式处理
csrw hedeleg, t1
# 注入虚拟中断
csrw hvip, t2
# 进入 Guest
sret
四、隔离与资源抽象:虚拟化的真正目标
隔离保证一个 Guest 的故障、越权或资源耗尽不会影响其他 Guest 与 Hypervisor。资源抽象则把 CPU、内存、中断、定时器、设备等物理资源包装成 Guest 可见的虚拟资源。二者相互支撑:没有隔离,抽象不可信;没有抽象,隔离难以落地。
在 RISC-V 中,隔离通常依赖以下机制:
- 特权级隔离:M 模式固件、HS 模式 Hypervisor、VS 模式 Guest、VU 模式 Guest 用户态,形成层级边界。
- 内存隔离:通过
hgatp与二级页表限制 Guest 只能访问被授权的宿主物理页。 - 中断隔离:通过
hedeleg/hideleg决定哪些中断由 Guest 直接处理,哪些必须陷入 Hypervisor。 - 设备隔离:MMIO 区域与 DMA 需经 IOMMU 或 Hypervisor 中介,防止 Guest 直接触碰他人内存。
五、案例:一个最小 RISC-V Guest 的启动路径
假设 Hypervisor 运行在 HS 模式,Guest 内核运行在 VS 模式。启动流程可简化为:
- Hypervisor 初始化
hgatp,为 Guest 建立 Guest 物理地址到宿主物理地址的映射。 - 设置
hedeleg,把非法指令、环境调用等异常委托给 VS 模式处理。 - 准备 Guest 的
sstatus、sepc与satp,使 Guest 使用自己的页表。 - 执行
sret进入 Guest;Guest 执行ecall时触发陷入,Hypervisor 根据scause分派处理。 - 定时器中断通过
hvip注入 Guest,Guest 的 VS 定时器处理程序完成调度。
这条路径体现了虚拟化的核心循环:抽象资源 → 运行 Guest → 捕获敏感事件 → 隔离处理 → 恢复 Guest。全虚拟化与半虚拟化的差异,主要体现在“捕获什么”和“Guest 是否配合”;硬件辅助虚拟化则决定了这个循环的代价有多低。
六、复盘:选择虚拟化方案时的判断清单
- Guest OS 是否允许修改?允许则半虚拟化 I/O 往往更高效。
- 硬件是否支持 H 扩展与二级页表?不支持则需影子页表,复杂度和开销都会上升。
- 隔离等级要求多高?多租户场景必须严格限制 MMIO、DMA 与中断委托。
- I/O 是性能瓶颈吗?若是,优先考虑 virtio 等半虚拟化设备模型。
- 是否需要实时性?Type-1 Hypervisor 配合中断委托与优先级调度更可控。
把 VMM 类型、全/半虚拟化、硬件辅助与隔离抽象放在同一张设计图上,才能回答“这个 RISC-V 虚拟化系统为什么这样分层、这样陷入、这样隔离”。