在操作系统的进程上下文切换中,操作系统与用户态程序运行在不同的特权级中,当用户态程序发起系统调用时,需要将部分程序状态保存在内存中,待系统调用完成后再从内存中恢复程序状态。而在虚拟化环境下,当虚拟机执行敏感指令时,需要陷入Hypervisor进行处理,Hypervisor与虚拟机同样运行在不同的特权级中,因此硬件应当提供一种机制在发生虚拟机下陷时保存虚拟机的上下文。等到敏感指令模拟完成后,当虚拟机恢复运行时重新加载虚拟机上下文。此处,“虚拟机上下文”表述可能有些不准确,更准确的说法应当是“vCPU上下文” 。一个虚拟机中可能包含多个vCPU,虚拟机中指令执行单元是vCPU,Hypervisor调度虚拟机运行的基本单位也是vCPU。当vCPU A执行敏感指令陷入Hypervisor时,vCPU B将会继续运行。在大部分Hypervisor中,vCPU对应一个线程,通过分时复用的方式共享物理CPU。以vCPU切换为例说明上下文切换的流程,vCPU切换流程如图2-2所示,其中实线表示控制流,虚线表示数据流。当vCPU 1时间片用尽时,Hypervisor将会中断vCPU 1执行,vCPU 1陷入Hypervisor中(见图2-2中标号I)。在此过程中,硬件将vCPU 1的寄存器状态保存至固定区域(见图2-2中标号①),并从中加载Hypervisor的寄存器状态(见图2-2中标号②)。Hypervisor进行vCPU调度,选择下一个运行的vCPU,保存Hypervisor的寄存器状态(见图2-2中标号③),并加载选定的vCPU 2的寄存器状态(见图2-2中标号④),而后恢复vCPU 2运行(见图2-2中标号II)。上述固定区域与系统架构实现密切相关。如在Intel VT-x中,虚拟机与Hypervisor寄存器状态保存在VMCS(Virtual Machine Control Structure,虚拟机控制结构)中,VMCS是内存中的一块固定区域,通过VMREAD/VMWRITE指令进行读写。而ARM v8则为EL1和EL2提供了两套系统寄存器,因此单纯发生虚拟机下陷时,无须保存寄存器状态;但是虚拟机下陷后,若要运行其他vCPU,则需要将上一个vCPU状态保存至内存中。后续章节将以Intel VT-x为例介绍上下文切换过程中VMCS的具体用法。
图2-2 vCPU切换流程
注:①保存vCPU寄存器;②加载Hypervisor寄存器;③保存Hypervisor寄存器;④加载vCPU寄存器;⑤指令执行顺序。