硬件辅助虚拟化

VT-x

VMCS
使用VMM(Virtual Machine Control Structure)控制虚拟机的状态,它包含了6个部分的内容:
Guest-state area: 当发生一次VM exit,CPU现在的状态被自动保存到这个区域中;VM Entry时,又将这个区域的内容加载到CPU中。Host-state area: 当发生VM exit时,可这个区域信息加载到CPU中;VM entry, 相反。VM-execution control field: 可以控制non-root模式中虚拟机的行为。VM-exit control field: 控制VM exit的行为。VM-entry control field: 控制VM entry的行为。VM-exit information field:VM exit的原因,方便VMM进行处理。
VM Entry and VM Exit
VM Entry会从root进入Non-root模式,第一次使用VMLAUNCH指令,之后会使用VMRESUME指令。
VM Exit会回到root模式,用于敏感指令检测和中断陷入。
ARM 虚拟化技术

VM Entry and VM Exit
对于eret 从VMM进入VM,这和操作系统进入用户态的操作是一样的。VMM虚拟化需要自己准备VM的上下文并加载,最后通过eret进入到VM中。
同样地,在vm exit时,即执行敏感指令或者受到中断时,需要VMM保存所有的状态,然后再执行VMM相关的处理程序。
ARMv8.0 Type-2 VMM架构

在EL2只能运行VMM, host os需要大量修改才能运行。这里的设计在EL2做了接受转发的lowvisor, 依靠原本Host OS的VMM模块进行处理。
ARMv8.1 Type-2 VMM架构
QEMU/KVM

由ARMv8.1提出的特性,我们可以设计出如上的架构,QEMU运行在用户态,负责实际的处理。同时KVM作为Linux的一个模块运行在EL2,负责对于敏感事件的捕捉,同时直接使用Linux提供的一些功能。
qemu使用ioctl向KVM传递命名,如CREATE_VM, CREATE_VCPU, KVM_RUN等。
open("/dev/kvm");
ioctl(KVM_CREATE_VM);
ioctl(KVM_CREATE_VCPU);
while(true) {
ioctl(KVM_RUN);
exit_reason = get_exit_reason();
switch (exit_reason) {
case KVM_EXIT_IO:
//....
break;
case KVM_EXIT_MMIO:
//...
break;
}
}
- 在
x86架构中,需要从VCPU中找到VMCS结构,使用CPU指令加载VMCS,使用VMLAUNCH或者VMRESUME进入到Non-root, 硬件会自动加载VMCS状态,跳转到GUEST_RIP执行。 - 对于
ARM,KVM会主动加载VCPU的所有状态,之后使用eret跳到guest程序执行。

上图中解释这个过程,KVM运行在高特权级充当媒介进行切换。下面是一个更加具体的例子

当一个VM中的程序执行了WFI时,就会被捕获VM Exit 到KVM,KVM处理程序主动将VCPU信息进行保留,根据handler执行相应的函数,它可以使用Linux中现有的一些机制,等待Kernel结果返回后,KVM还可以调度下一个VM程序。

对于一个IO类型的VM Exit的陷入还射击QEMU,QEMU运行在用户态,但是由于v8.1中提到的特性这是允许的,QEMU处理完IO可以通过系统调用返回。