01 kvm_main 核心机制与实现详解
1. 文件角色
virt/kvm/kvm_main.c(约 6000+ 行)是 所有架构共享的 KVM 核心:字符设备、VM/VCPU 生命周期、Guest 内存槽、MMU notifier、调试fs、停机轮询(halt poll)、与 kvm_arch_* 协作的枢纽。
文件头注释仍提及 Intel VT-x 历史;现代 ARM64 同样依赖此文件的 通用 ioctl 与资源管理。
2. 模块入口与 /dev/kvm
1 | static struct miscdevice kvm_dev = { |
kvm_dev_ioctl 处理:
| ioctl | 行为 |
|---|---|
KVM_GET_API_VERSION |
返回 KVM_API_VERSION |
KVM_CREATE_VM |
kvm_dev_ioctl_create_vm → anon_inode + kvm_vm_fops |
KVM_CHECK_EXTENSION |
能力探测(含 arch 扩展) |
KVM_GET_VCPU_MMAP_SIZE |
kvm_run 映射大小(+ 可选 coalesced mmio 页) |
| 其它 | kvm_arch_dev_ioctl(架构特定) |
KVM_CREATE_VM 流程:
get_unused_fd_flags;kvm_create_vm(type, fdname)→ 分配struct kvm,调用kvm_arch_init_vm;anon_inode_getfile("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);fd_install返回 VM fd。
3. 三级 file_operations
- VM ioctl:内存区域、irq 路由、寄存器级设备、dirty log 等;
- VCPU ioctl:
KVM_RUN、寄存器 get/set、中断、调试; - KVM device ioctl(
kvm_device_ioctl):API 2.0 设备模型(如 VFIO 设备、架构 vGIC 设备在 arch 注册)。
4. VCPU 运行与请求机制
vcpu_load/vcpu_put:绑定 VCPU 到当前 CPU,准备进入 guest;kvm_make_vcpu_request:设置vcpu->requests位(TLB flush、kick 等);kvm_kick_many_cpus:IPI 唤醒执行KVM_RUN的线程;halt_poll_ns:guest halt 时自旋轮询再阻塞,降低唤醒延迟(模块参数可调)。
ARM64:kvm_arch_vcpu_should_kick 在 arm.c 根据 IN_GUEST_MODE 判断。
5. Guest 内存(memslots)
用户态通过 KVM_SET_USER_MEMORY_REGION 注册 GPA→HVA 区间:
- 内核维护 address space 与 memory slots;
- 与 mmu_notifier 挂钩:host 页面迁移/释放时
kvm_mmu_notifier_invalidate_range使 guest 映射失效; - huge page、read-only memslot、private memslot 等由通用层 + arch 支持。
kvm_pfn_to_refcounted_page、kvm_is_zone_device_page 处理特殊内存类型。
6. TLB 与影子页表
kvm_flush_remote_tlbs:请求所有 VCPU 刷新 guest TLB(调用kvm_arch_flush_remote_tlbs);kvm_flush_shadow_all:MMU shadow 相关(x86 为主,ARM 使用 Stage-2 由mmu.c实现)。
7. mmu_notifier
当 host 进程内存被 pin/unpin、migrate、munmap 时:
1 | static void kvm_mmu_notifier_invalidate_range(struct mmu_notifier *mn, ...) |
保证 QEMU 用户态内存 与 guest 物理地址 一致性,是 KVM 正确性的基石。
8. 调试与统计
kvm_debugfs_dir:debugfs 入口(/sys/kernel/debug/kvm/);binary_stats.c:向用户态导出二进制统计(配合tools/perf等生态);- tracepoints:
trace/events/kvm.h,CREATE_TRACE_POINTS在kvm_main.c。
9. 弱符号扩展点
架构未实现时使用空 weak 函数,例如:
1 | __weak void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm, ...) { } |
ARM64 在 mmu.c 等提供强符号覆盖。
10. 与 RK3588 的关系
- RK3588 启用 KVM 时,所有 VM 创建/内存注册 均经
kvm_main.c; - 异常退出、系统寄存器、VGIC 不在此文件;
- 调优 halt poll 可影响虚拟 Android/VM 的 idle 延迟与 host CPU 占用。
11. 小结
kvm_main.c = KVM 资源管理与 ioctl 中枢;读 ARM KVM 须以此为基础,再进入 05-ARM64边界 的 arm.c/handle_exit.c。
正在加载留言…