3.1. CPU虚拟化之基本原理

文章目录

  • 1. VT-x 技术
  • 2. VMM 与 guest的切换
  • 3. VMM 的生命周期
  • 4. VMCS(Virtual-Machine control structure)
  • 5. VM-Entry
  • 6. VM-Exit
  • 7. 参考

1. VT-x 技术

Intel处理器支持的虚拟化技术即是VT-x,之所以CPU支持硬件虚拟化是因为软件虚拟化的效率太低。

kvm分3个模式,对应到VT-x中即是

  1. 客户模式对应vmx非root模式
  2. 内核模式对应VMX root模式下的0特权级
  3. 用户模式对应vmx root模式下的3特权级

3.1. CPU虚拟化之基本原理_第1张图片

在非根模式下敏感指令引发的陷入称为VM-ExitVM-Exit发生后,CPU从非根模式切换到根模式;对应的,VM-Entry则是从根模式到非根模式,通常意味着调用VM进入运行态。VMLAUCH/VMRESUME命令则是用来发起VM-Entry

  1. VMM完成vCPU,内存的初始化后,通过ioctl调用KVM的接口,完成虚拟机的创建,并创建一个线程来运行VM,由于VM在前期初始化的时候会设置各种寄存器来帮助KVM查找到需要加载的指令的入口(main函数)。所以线程在调用了KVM接口后,物理CPU的控制权就交给了VM

  2. VM运行在VMX non-root模式,这是Intel-V或者AMD-V提供的一种特殊的CPU执行模式。然后当VM执行了特殊指令的时候,CPU将当前VM的上下文保存到VMCS寄存器(这个寄存器是一个指针,保存了实际的上下文地址),然后执行权切换到VMM。

  3. VMM 获取 VM 返回原因,并做处理。如果是IO请求,VMM 可以直接读取VM的内存并将IO操作模拟出来,然后再调用VMRESUME指令,VM继续执行,此时在VM看来IO操作的指令CPU执行了。

2. VMM 与 guest的切换

3.1. CPU虚拟化之基本原理_第2张图片

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-EntryVMRESUME则是VMLAUCH之后后续的VM-Entry

VMCS下有一些控制域

3.1. CPU虚拟化之基本原理_第3张图片

关于具体控制域的细节,还是翻Intel手册吧。

5. VM-Entry

VM-Entry是从根模式切换到非根模式,即VMM切换到guest上,这个状态由VMM发起发起之前先保存VMM中的关键寄存器内容到VMCS中,然后进入到VM-Entry,VM-Entry附带参数主要有3个

  1. guest是否处于64bit模式,
  2. MSR VM-Entry控制,
  3. 注入事件

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个方面:

  1. 行为没有变化的,也就是说该指令能够正确执行

  2. 行为有变化的,直接产生VM-Exit

  3. 行为有变化的,但是是否产生VM-Exit受到VM-Execution控制域控制

主要说一下"受到VM-Execution控制域控制"的敏感指令,这个就是针对性的硬件优化了,一般是

  1. 产生VM-Exit
  2. 不产生VM-Exit,同时调用优化函数完成功能

典型的有“RDTSC指令”。除了大部分是优化性能的,还有一小部分是直接VM-Exit执行指令结果是异常的,或者说在虚拟化场景下是不适用的,典型的就是TSC offset了。

VM-Exit发生时退出的相关信息,如退出原因、触发中断等,这些内容保存在VM-Exit信息域中。

7. 参考

http://oenhan.com/kvm-src-3-cpu

你可能感兴趣的:(QEMU-KVM之KVM,#,3.,kvm之CPU虚拟化,linux,qemu,kvm)