讲到intel的cpu虚拟化,就不得不提到vt-x。vt-x是intel的CPU硬件虚拟化技术,但是在操作系统内部查看cpu的flag时,是否支持硬件虚拟化的的判断标准是是否有vmx,vmx是什么,它和虚拟化有什么关系,本文将会涉及到。
几个基础概念
1.VMM:
虚拟机监视器在宿主机上表现为一个提供虚拟机CPU,内存以及一系列硬件虚拟的实体,这个实体在KVM体系中就是一个进程,如qemu-kvm。VMM负责管理虚拟机的资源,并拥有所有虚拟机资源的控制权,包括切换虚拟机的CPU上下文等。
2.Guest:
可能是一个操作系统(OS),也可能就是一个二进制程序。对于VMM来说,他就是一堆指令集,只需要知道入口(rip寄存器值)就可以加载。
Guest运行需要虚拟CPU,当Guest代码运行的时候,处于VMX non-root模式,此模式下,该用什么指令还是用什么指令,该用什么寄存器还用什么寄存器,该用cache还是用cache,但是在执行到特殊指令的时候(比如Demo中的out指令),把CPU控制权交给VMM,由VMM来处理特殊指令,完成硬件操作。
3.CPU运行级别:
CPU支持ring0~ring3 4个等级,但是Linux只使用了其中的两个ring0,ring3。当CPU寄存器标示了当前CPU处于ring0级别的时候,表示此时CPU正在运行的是内核的代码。而当CPU处于ring3级别的时候,表示此时CPU正在运行的是用户级别的代码。当发生系统调用或者进程切换的时候,CPU会从ring3级别转到ring0级别。ring3级别是不允许执行硬件操作的,所有硬件操作都需要内核提供的系统调用来完成。
4.VMX:
为了从CPU层面支持VT技术,Intel-V 在 ring0~ring3 的基础上, 扩展了传统的x86处理器架构,引入了VMX模式,VMX分为root和non-root。VMM运行在VMX root模式;Guest运行在VMX non-root模式。
CPU虚拟化
有了cpu的运行级别和VMX,就可以看一下CPU虚拟化的基本运行情况了。
Guest OS里的内核运行于VMX non-root下的ring0
Guest OS里的应用程序运行于VMX non-root模式下的ring3
Host OS的内核和VMM运行于VMX root模式下的ring0。
虽然GuestOS的内核也运行于ring0,但是由于是non-root模式,所以不能操作某些资源,不能运行敏感指令。
Guest也分ring0~ring3,不过他并不感知自己处于VMX non-root模式下。
VMM与Guest的切换
1. VM entry 和 VM exit
Guest与VMM之间的切换有两个过程:VM entry 和 VM exit。Guest运行时处于VMX下的non-root模式,当执行了特殊操作的时候(具体哪种操作后面的VM exit原因中会提到),通过VM exit将cpu控制权返回给VMM,从而陷入到root模式下的ring0内的VMM,进行“陷入模拟”。 VMM处理完特殊操作后再通过VM entry把结果和控制权返回给Guest。
2.导致VM exit的原因
导致VM exit的原因有多种,例如Guest执行了硬件IO访问操作,或者Guest调用了VMCALL指令,或者调用了退出指令,或者产生了一个page fault,或者访问了特殊设备的寄存器等。在内核中有关于VM exit原因的列表。
3.VMCS:(虚拟机控制结构)
这是虚拟机的户口本,对虚拟机至关重要。Guest Exit的时候,会将当前Guest的上下文保存到VMCS中,Guest entry的时候把VMCS上下文恢复给VMM。VMCS是一个64位的指针,指向一个真实的内存地址,VMCS是以vCPU为单位的,即Guest有多少个vCPU,就对应多少个VMCS指针。VMCS的操作包括VMREAD,VMWRITE,VMCLEAR。
当Guest发起执行的指令处于VMX模式(包括运行VMM的root和运行Guest代码的non-root)的时候,Guest不能判断当前CPU是否处于VMX模式还是非VMX模式。当产生VM exit的时候,CPU会将exit reason保存到MSRs(VMX模式的特殊寄存器组),对应到KVM就是vCPU->kvm_run->exit_reason。VMM再根据exit_reason做相应的处理。所以MSRs寄存器就成了Guest和VMX交接的中间人。
关于Intel的cpu虚拟化的详细说明可参考:
关注本公众号,了解更多关于云计算虚拟化的知识。