硬件虚拟化让一个 CPU 上运行多个 OS → 但每次 VM-exit 都有代价。
一、先看图
flowchart TD
GUEST[Guest OS] -->|敏感指令| VMEXIT[VM-exit<br/>陷入 VMM]
VMEXIT --> VMM[VMM / Hypervisor<br/>处理]
VMM --> VMENTRY[VM-entry<br/>返回 Guest]
VMENTRY --> GUEST
GUEST2[Guest 内存访问] --> EPT[EPT/NPT<br/>二级页表翻译]
EPT --> PHYS[物理内存]
classDef guest fill:#388bfd22,stroke:#388bfd,color:#adbac7;
classDef vmm fill:#f0883e22,stroke:#f0883e,color:#adbac7;
class GUEST,GUEST2,VMENTRY guest
class VMEXIT,VMM vmm
class EPT,PHYS guest
二、硬件支持
2.1 Intel VT-x(VMX)
VMXON → 启用 VMX 模式
VMLAUNCH/VMRESUME → 进入 Guest(VM-entry)
Guest 执行敏感指令 → VM-exit → 回到 VMM
VMCS(Virtual Machine Control Structure)控制 VM-exit 条件。
2.2 AMD-V(SVM)
VMRUN → 进入 Guest
#VMEXIT → 回到 Host
VMCB(Virtual Machine Control Block)= AMD 版 VMCS。
三、VM-exit 原因
| 原因 | 说明 |
|---|---|
| I/O 指令 | in/out |
| MSR 访问 | rdmsr/wrmsr |
| 中断 | 外部中断 |
| CPUID | CPU 特性查询 |
| EPT violation | 内存映射缺失 |
| HLT | CPU 空闲 |
四、EPT / NPT
4.1 问题
Guest 页表:GVA → GPA(Guest Physical Address)
需要再翻译:GPA → HPA(Host Physical Address)
4.2 二级页表
GVA → Guest 页表 → GPA → EPT/NPT → HPA
硬件自动完成两级翻译 → 不需要 VMM 介入 → 大幅减少 VM-exit。
4.3 代价
TLB miss 时需要遍历两级页表 → 最多 24 次内存访问(4 级 × 4 级 + TLB 填充)。
五、APICv 与 Posted Interrupts
传统:Guest 的中断 → VM-exit → VMM 注入。
APICv:硬件直接将中断送到 Guest → 不需要 VM-exit。
Posted Interrupt = 硬件把中断写入 Guest 的虚拟 APIC → 直接唤醒 vCPU
六、vCPU 调度
vCPU 是宿主的线程 → 由宿主调度器调度。
问题:
- vCPU 被抢占时持有 Guest spinlock → 其他 vCPU 自旋等待(Lock Holder Preemption)
- 解决:PV spinlock → Guest 检测到 vCPU 被抢占 → 让出
七、Nested Virtualization
L0(硬件)→ L1(Host VMM)→ L2(Guest VMM)→ L3(Guest)
L2 的 VM-exit → 可能需要 L1 处理 → 性能开销大。
八、PV(Paravirtualization)
Guest 知道自己在虚拟化环境中 → 使用优化的接口:
| PV 机制 | 用途 |
|---|---|
| PV clock | 时钟同步 |
| PV spinlock | 避免 lock holder preemption |
| PV TLB flush | 批量 TLB flush |
| virtio | I/O 虚拟化 |
九、观察
# 检查硬件虚拟化支持
grep -cE 'vmx|svm' /proc/cpuinfo
# KVM 模块
lsmod | grep kvm
# VM-exit 统计(在 Host 上)
perf kvm stat live
# Guest 内
dmesg | grep -i "hypervisor\|kvm\|vmware"十、小结
- VMX/SVM 提供硬件虚拟化 → VM-exit/VM-entry 切换
- EPT/NPT 二级页表减少内存访问的 VM-exit
- APICv + posted interrupts 减少中断的 VM-exit
- vCPU 调度要注意 lock holder preemption
- PV 接口进一步优化性能
参考文献
- Intel SDM Volume 3, Chapter 23-28(VMX)
- AMD APM Volume 2, Chapter 15(SVM)
arch/x86/kvm/Documentation/virt/kvm/
工具
perf kvm/proc/cpuinfovirsh
文章导航
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
CPU 调度:CFS 的虚拟运行时间与 EEVDF 的虚拟截止期
从比例份额调度的论文谱系出发,对照 Linux v6.6 与 v6.12 fair.c 源码,解释 CFS 的 vruntime、EEVDF 的 lag/eligible/deadline,并用确定性模拟复现延迟与 lag 的差异。
I/O 调度:在寻道、队列深度与公平性之间取舍
从电梯算法到 blk-mq,解释 Linux I/O 调度器为何在 HDD 上排序、在共享设备上保公平、在 NVMe 上常选择 none,并用确定性模拟展示寻道距离与队列尾延迟的取舍。
用户态内存分配器:size class、线程缓存与碎片边界
从 Wilson 分配器综述到 jemalloc、gperftools tcmalloc 与 mimalloc 的源码路径,解释 size class、线程缓存、跨线程释放和 RSS 碎片;用可复现实验说明不能只凭 allocator 名字下结论。
伙伴系统与 SLUB:Linux 物理页和小对象分配的边界
以 Linux v6.6 源码和确定性模拟为准,解释伙伴系统的 split/coalesce、migratetype 反碎片策略,以及 SLUB 的 per-CPU freelist、partial list 与安全加固。