设为首页 收藏本站
云服务器等爆品抢先购,低至4.2元/月
查看: 2391|回复: 0

[经验分享] [原] KVM 虚拟化原理探究(3)

[复制链接]

尚未签到

发表于 2017-6-24 07:42:25 | 显示全部楼层 |阅读模式
KVM 虚拟化原理探究(3)— CPU 虚拟化
  标签(空格分隔): KVM
  [TOC]

CPU 虚拟化简介
  上一篇文章笼统的介绍了一个虚拟机的诞生过程,从demo中也可以看到,运行一个虚拟机再也不需要像以前想象的那样,需要用软件来模拟硬件指令集了。虚拟机的指令集直接运行在宿主机物理CPU上,当虚拟机中的指令设计到IO操作或者一些特殊指令的时候,控制权转让给了宿主机(这里其实是转让给了vm monitor,下面检查VMM),也就是一个demo进程,他在宿主机上的表现形式也就是一个用户级进程。
  用一张图来解释更为贴切。
DSC0000.png

  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执行了。

Intel-V 技术
  Intel-V 技术是Intel为了支持虚拟化而提供的一套CPU特殊运行模式。

Intel-V虚拟化技术结构
  Intel-V 在IA-32处理器上扩展了处理器等级,原来的CPU支持ring0~ring3 4个等级,但是Linux只使用了其中的两个ring0,ring3。当CPU寄存器标示了当前CPU处于ring0级别的时候,表示此时CPU正在运行的是内核的代码。而当CPU处于ring3级别的时候,表示此时CPU正在运行的是用户级别的代码。当发生系统调用或者进程切换的时候,CPU会从ring3级别转到ring0级别。ring3级别是不允许执行硬件操作的,所有硬件操作都需要系统提供的API来完成。
  
比如说一个IO操作:
  

int nread = read(fd, buffer, 1024);  

  当执行到此段代码的时候,然后查找到系统调用号,保存到寄存器eax,然后会将对应的参数压栈后产生一个系统调用中断,对应的是 int $0x80。产生了系统调用中断后,此时CPU将切换到ring0模式,内核通过寄存器读取到参数,并完成最后的IO后续操作,操作完成后返回ring3模式。
  

movel  $3,%eax  
movel  fd,%ebx
  
movel  buffer,%ecx
  
movel  1024,%edx      
  
int    $0x80
  

  Intel-V 在 ring0~ring3 的基础上,增加了VMX模式,VMX分为root和non-root。这里的VMX root模式是给VMM(前面有提到VM monitor),在KVM体系中,就是qemu-kvm进程所运行的模式。VMX non-root模式就是运行的Guest,Guest也分ring0~ring3,不过他并不感知自己处于VMX non-root模式下。
DSC0001.png

  Intel的虚拟架构基本上分两个部分:


  • 虚拟机监视器
  • 客户机(Guest VM)
虚拟机监视器(Virtual-machine monitors - VMM)
  虚拟机监视器在宿主机上表现为一个提供虚拟机CPU,内存以及一系列硬件虚拟的实体,这个实体在KVM体系中就是一个进程,如qemu-kvm。VMM负责管理虚拟机的资源,并拥有所有虚拟机资源的控制权,包括切换虚拟机的CPU上下文等。

Guest
  这个Guest在前面的Demo里面也提到,可能是一个操作系统(OS),也可能就是一个二进制程序,whatever,对于VMM来说,他就是一堆指令集,只需要知道入口(rip寄存器值)就可以加载。
  
Guest运行需要虚拟CPU,当Guest代码运行的时候,处于VMX non-root模式,此模式下,该用什么指令还是用什么指令,该用寄存器该用cache还是用cache,但是在执行到特殊指令的时候(比如Demo中的out指令),把CPU控制权交给VMM,由VMM来处理特殊指令,完成硬件操作。

VMM 与 Guest 的切换
DSC0002.png

  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做相应的处理。

VMM 的生命周期
  如上图所示,VMM 开始于VMXON 指令,结束与VMXOFF指令。
  
第一次启动Guest,通过VMLAUNCH指令加载Guest,这时候一切都是新的,比如说起始的rip寄存器等。后续Guest exit后再entry,是通过VMRESUME指令,此指令会将VMCS(后面会介绍到)所指向的内容加载到当前Guest的上下文,以便Guest继续执行。

VMCS (Virtual-Machine control structure)
  顾名思义,VMCS就是虚拟机控制结构,前面提到过很多次,Guest Exit的时候,会将当前Guest的上下文保存到VMCS中,Guest entry的时候把VMCS上下文恢复到VMM。VMCS是一个64位的指针,指向一个真实的内存地址,VMCS是以vCPU为单位的,就是说当前有多少个vCPU,就有多少个VMCS指针。VMCS的操作包括VMREAD,VMWRITE,VMCLEAR。

Guest exit Reason
  下面是qemu-kvm定义的exit reason。可以看到有很多可能会导致Guest转让控制权。选取几个解释一下。
  

static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {  [EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
  [EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
  [EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
  [EXIT_REASON_NMI_WINDOW]              = handle_nmi_window,
  // 访问了IO设备
  [EXIT_REASON_IO_INSTRUCTION]          = handle_io,
  // 访问了CR寄存器,地址寄存器,和DR寄存器(debug register)一样,用于调试
  [EXIT_REASON_CR_ACCESS]               = handle_cr,
  [EXIT_REASON_DR_ACCESS]               = handle_dr,
  [EXIT_REASON_CPUID]                   = handle_cpuid,
  // 访问了MSR寄存器
  [EXIT_REASON_MSR_READ]                = handle_rdmsr,
  [EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
  [EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
  // Guest执行了HLT指令,Demo开胃菜就是这个指令
  [EXIT_REASON_HLT]                     = handle_halt,
  [EXIT_REASON_INVD]                    = handle_invd,
  [EXIT_REASON_INVLPG]                  = handle_invlpg,
  [EXIT_REASON_RDPMC]                   = handle_rdpmc,
  // 不太清楚以下VM系列的指令有什么用,猜测是递归VM(虚拟机里面运行虚拟机)
  [EXIT_REASON_VMCALL]                  = handle_vmcall,
  [EXIT_REASON_VMCLEAR]                 = handle_vmclear,
  [EXIT_REASON_VMLAUNCH]                = handle_vmlaunch,
  [EXIT_REASON_VMPTRLD]                 = handle_vmptrld,
  [EXIT_REASON_VMPTRST]                 = handle_vmptrst,
  [EXIT_REASON_VMREAD]                  = handle_vmread,
  [EXIT_REASON_VMRESUME]                = handle_vmresume,
  [EXIT_REASON_VMWRITE]                 = handle_vmwrite,
  [EXIT_REASON_VMOFF]                   = handle_vmoff,
  [EXIT_REASON_VMON]                    = handle_vmon,
  [EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
  // 访问了高级PCI设备
  [EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
  [EXIT_REASON_APIC_WRITE]              = handle_apic_write,
  [EXIT_REASON_EOI_INDUCED]             = handle_apic_eoi_induced,
  [EXIT_REASON_WBINVD]                  = handle_wbinvd,
  [EXIT_REASON_XSETBV]                  = handle_xsetbv,
  // 进程切换
  [EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
  [EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
  // ept 是Intel的一个硬件内存虚拟化技术
  [EXIT_REASON_EPT_VIOLATION]           = handle_ept_violation,
  [EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
  // 执行了暂停指令
  [EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
  [EXIT_REASON_MWAIT_INSTRUCTION]       = handle_invalid_op,
  [EXIT_REASON_MONITOR_INSTRUCTION]     = handle_invalid_op,
  [EXIT_REASON_INVEPT]                  = handle_invept,
  
};
  

总结
  KVM的CPU虚拟化依托于Intel-V提供的虚拟化技术,将Guest运行于VMX模式,当执行了特殊操作的时候,将控制权返回给VMM。VMM处理完特殊操作后再把结果返回给Guest。
  
CPU虚拟化可以说是KVM的最关键的核心,弄清楚了VM Exit和VM Entry。后续的IO虚拟化,内存虚拟化都是建立在此基础上。下一章介绍内存虚拟化。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-387457-1-1.html 上篇帖子: kvm与selinux 下篇帖子: 3.kvm的基本管理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表