30 两个世界,一个CPU:虚拟化中的root操作和非root操作
# 30 两个世界,一个CPU:虚拟化中的root操作和非root操作
现代英特尔处理器的虚拟化依赖于通过虚拟机扩展(VMX,Virtual Machine Extensions)建立的执行环境的严格划分。这种分离定义了两个操作世界:VMX root模式和VMX非root模式,从而在CPU的严格控制下实现安全、高效的虚拟化。
当KVM模块设置了CR4.VMXE并执行VMXON时,VMX操作开始,将CPU转换为root模式并启用VMX指令。在客户机运行之前,KVM为每个虚拟CPU(vCPU)分配并配置一个虚拟机控制结构(VMCS,Virtual Machine Control Structure),其中包含客户机和主机处理器状态以及执行和控制字段。
客户机执行以VMLAUNCH开始或以VMRESUME恢复。CPU从VMCS加载客户机状态并进入VMX非root模式。在这种模式下,客户机操作系统直接在硬件上运行,同时与主机隔离,即使在 0 环(ring 0)执行也是如此。
大多数客户机指令在执行时无需虚拟机管理程序干预,除非被VMCS控制所禁止。特权指令、I/O端口访问、控制寄存器修改或外部中断会触发VM退出。在VM退出期间,CPU将客户机状态保存到 VMCS 中,恢复主机状态,记录退出原因,并将控制权交还给在root模式下运行的KVM。
KVM读取退出原因并处理该事件。CPU状态更改、特权操作或中断处理直接在内核中处理,而设备访问或用户驱动的事件则转发给QEMU等用户空间监视器。如果vCPU线程被抢占,KVM会保存客户机上下文并让步给Linux调度器。
在vCPU之间切换时,KVM使用VMPTRLD加载新vCPU的专用VMCS。每个vCPU维护自己的VMCS,切换涉及更新活动VMCS指针以确保客户机之间的隔离。Linux调度器将vCPU视为普通线程,允许在vCPU之间或客户机与主机进程之间进行公平调度。
重新调度后,当再次选择vCPU时,KVM会根据需要更新VMCS,并使用VMRESUME恢复客户机执行。
VMCS在转换过程中维护处理器状态,包括通用寄存器、控制寄存器、指令指针、标志和执行控制。对VMCS字段的精心管理可最大限度地减少开销、保持隔离并确保客户机行为正确。
客户机和主机之间的内存一致性通过INVEPT和INVVPID等指令维护,从而能够选择性地使地址映射和TLB条目失效,而无需完全刷新处理器。
当客户机终止时,KVM发出VMXOFF,结束VMX操作并将CPU恢复为正常的主机执行。
通过root模式和非root模式之间的结构化划分、每个vCPU的专用VMCS结构以及KVM转换的协调,现代处理器提供了安全高效的硬件虚拟化。