3.1. CPU虚拟化之基本原理
文章目录
1. VT-x 技术
Intel处理器支持的虚拟化技术即是VT-x,之所以CPU支持硬件虚拟化是因为软件虚拟化的效率太低。
kvm分3个模式,对应到VT-x中即是
- 客户模式对应vmx非root模式
- 内核模式对应VMX root模式下的0特权级
- 用户模式对应vmx root模式下的3特权级
在非根模式下敏感指令引发的陷入称为VM-Exit
,VM-Exit
发生后,CPU从非根模式切换到根模式;对应的,VM-Entry
则是从根模式到非根模式,通常意味着调用VM进入运行态。VMLAUCH
/VMRESUME
命令则是用来发起VM-Entry
。
-
VMM完成vCPU,内存的初始化后,通过ioctl调用KVM的接口,完成虚拟机的创建,并创建一个线程来运行VM,由于VM在前期初始化的时候会设置各种寄存器来帮助KVM查找到需要加载的指令的入口(main函数)。所以线程在调用了KVM接口后,物理CPU的控制权就交给了VM。
-
VM运行在VMX non-root模式,这是Intel-V或者AMD-V提供的一种特殊的CPU执行模式。然后当VM执行了特殊指令的时候,CPU将当前VM的上下文保存到VMCS寄存器(这个寄存器是一个指针,保存了实际的上下文地址),然后执行权切换到VMM。
-
VMM 获取 VM 返回原因,并做处理。如果是IO请求,VMM 可以直接读取VM的内存并将IO操作模拟出来,然后再调用VMRESUME指令,VM继续执行,此时在VM看来,IO操作的指令被CPU执行了。
2. VMM 与 guest的切换
Guest与VMM之间的切换分两个部分:VM entry 和 VM exit。有几种情况会导致VM exit,比如说Guest执行了硬件访问操作,或者Guest调用了VMCALL指令或者调用了退出指令或者产生了一个page fault,或者访问了特殊设备的寄存器等。当Guest处于VMX模式的时候,没有提供获取是否处于此模式下的指令或者寄存器,也就是说,Guest不能判断当前CPU是否处于VMX模式。
当产生VM exit的时候,CPU会将exit reason保存到MSRs(VMX模式的特殊寄存器组),对应到KVM就是vCPU->kvm_run->exit_reason
。VMM根据exit_reason
做相应的处理。
3. VMM 的生命周期
如上图所示,VMM 开始于 VMXON 指令,结束与 VMXOFF 指令。
第一次启动Guest,通过 VMLAUNCH 指令加载Guest,这时候一切都是新的,比如说起始的rip寄存器等。后续Guest exit后再entry,是通过 VMRESUME 指令,此指令会将VMCS(后面会介绍到)所指向的内容加载到当前Guest的上下文,以便Guest继续执行。
4. VMCS(Virtual-Machine control structure)
顾名思义,VMCS就是虚拟机控制结构,前面提到过很多次,Guest Exit的时候,会将当前Guest的上下文保存到VMCS中,Guest entry的时候把VMCS上下文恢复到VMM。VMCS是一个64位的指针,指向一个真实的内存地址,VMCS是以vCPU为单位的,就是说当前有多少个vCPU,就有多少个VMCS指针。VMCS的操作包括VMREAD,VMWRITE,VMCLEAR。
VMCS保存虚拟机的相关CPU状态,每个VCPU都有一个VMCS(内存的),每个物理CPU都有VMCS对应的寄存器(物理的).
- 当CPU发生
VM-Entry
时,CPU则从VCPU指定的内存中读取VMCS加载到物理CPU上执行; - 当发生
VM-Exit
时,CPU则将当前的CPU状态保存到VCPU指定的内存中,即VMCS,以备下次VMRESUME
。
VMLAUCH
指VM的第一次VM-Entry
,VMRESUME
则是VMLAUCH之后后续的VM-Entry
。
VMCS下有一些控制域:
关于具体控制域的细节,还是翻Intel手册吧。
5. VM-Entry
VM-Entry
是从根模式切换到非根模式,即VMM切换到guest上,这个状态由VMM发起,发起之前先保存VMM中的关键寄存器内容到VMCS中,然后进入到VM-Entry,VM-Entry
附带参数主要有3个:
- guest是否处于64bit模式,
-
MSR VM-Entry
控制, - 注入事件。
1应该只在VMLAUCH有意义,3更多是在VMRESUME,而VMM发起VM-Entry
更多是因为3,2主要用来每次更新MSR。
第一次启动Guest,通过VMLAUNCH指令加载Guest,这时候一切都是新的,比如说起始的rip寄存器等。 后续Guest exit后再entry,是通过VMRESUME指令,此指令会将VMCS所指向的内容加载到当前Guest的上下文, 以便Guest继续执行。
6. VM-Exit
VM-Exit
是CPU从非根模式切换到根模式,从guest切换到VMM的操作,VM-Exit
触发的原因就很多了,执行敏感指令,发生中断,模拟特权资源等。
运行在非根模式下的敏感指令一般分为3个方面:
-
行为没有变化的,也就是说该指令能够正确执行。
-
行为有变化的,直接产生
VM-Exit
。 -
行为有变化的,但是是否产生
VM-Exit
受到VM-Execution
控制域控制。
主要说一下"受到VM-Execution
控制域控制"的敏感指令,这个就是针对性的硬件优化了,一般是
- 产生
VM-Exit
; - 不产生
VM-Exit
,同时调用优化函数完成功能。
典型的有“RDTSC指令”。除了大部分是优化性能的,还有一小部分是直接VM-Exit
执行指令结果是异常的,或者说在虚拟化场景下是不适用的,典型的就是TSC offset了。
VM-Exit
发生时退出的相关信息,如退出原因、触发中断等,这些内容保存在VM-Exit
信息域中。
7. 参考
http://oenhan.com/kvm-src-3-cpu