设为首页 收藏本站
查看: 1183|回复: 0

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

[复制链接]

尚未签到

发表于 2017-6-24 13:18:55 | 显示全部楼层 |阅读模式
KVM 虚拟化原理探究(4)— 内存虚拟化
  标签(空格分隔): KVM

内存虚拟化简介
  前一章介绍了CPU虚拟化的内容,这一章介绍一下KVM的内存虚拟化原理。可以说内存是除了CPU外最重要的组件,Guest最终使用的还是宿主机的内存,所以内存虚拟化其实就是关于如何做Guest到宿主机物理内存之间的各种地址转换,如何转换会让转换效率更高呢,KVM经历了三代的内存虚拟化技术,大大加快了内存的访问速率。

传统的地址转换
  在保护模式下,普通的应用进程使用的都是自己的虚拟地址空间,一个64位的机器上的每一个进程都可以访问0到2^64的地址范围,实际上内存并没有这么多,也不会给你这么多。对于进程而言,他拥有所有的内存,对内核而言,只分配了一小段内存给进程,待进程需要更多的进程的时候再分配给进程。
  
通常应用进程所使用的内存叫做虚拟地址,而内核所使用的是物理内存。内核负责为每个进程维护虚拟地址到物理内存的转换关系映射。
  
首先,逻辑地址需要转换为线性地址,然后由线性地址转换为物理地址。
  

逻辑地址 ==> 线性地址 ==> 物理地址  

  逻辑地址和线性地址之间通过简单的偏移来完成。
  
DSC0000.png
  一个完整的逻辑地址 = [段选择符:段内偏移地址],查找GDT或者LDT(通过寄存器gdtr,ldtr)找到描述符,通过段选择符(selector)前13位在段描述符做index,找到Base地址,Base+offset就是线性地址。
  为什么要这么做?据说是Intel为了保证兼容性。
  逻辑地址到线性地址的转换在虚拟化中没有太多的需要介绍的,这一层不存在实际的虚拟化操作,和传统方式一样,最重要的是线性地址到物理地址这一层的转换。
  传统的线性地址到物理地址的转换由CPU的页式内存管理,页式内存管理。
  
页式内存管理负责将线性地址转换到物理地址,一个线性地址被分五段描述,第一段为基地址,通过与当前CR3寄存器(CR3寄存器每个进程有一个,线程共享,当发生进程切换的时候,CR3被载入到对应的寄存器中,这也是各个进程的内存隔离的基础)做运算,得到页表的地址index,通过四次运算,最终得到一个大小为4K的页(有可能更大,比如设置了hugepages以后)。整个过程都是CPU完成,进程不需要参与其中,如果在查询中发现页已经存在,直接返回物理地址,如果页不存在,那么将产生一个缺页中断,内核负责处理缺页中断,并把页加载到页表中,中断返回后,CPU获取到页地址后继续进行运算。
DSC0001.png


KVM中的内存结构
  由于qemu-kvm进程在宿主机上作为一个普通进程,那对于Guest而言,需要的转换过程就是这样。
  

  Guest虚拟内存地址(GVA)  |
  Guest线性地址
  |
  Guest物理地址(GPA)
  |             Guest
  ------------------
  |             HV
  HV虚拟地址(HVA)
  |
  HV线性地址
  |
  HV物理地址(HPA)
  

  What's the fu*k ?这么多...
  
别着急,Guest虚拟地址到HV线性地址之间的转换和HV虚拟地址到线性地址的转换过程可以省略,这样看起来就更清晰一点。
  

  Guest虚拟内存地址(GVA)  |
  Guest物理地址(GPA)
  |             Guest
  ------------------
  |             HV
  HV虚拟地址(HVA)
  |
  HV物理地址(HPA)
  

  前面也说到KVM通过不断的改进转换过程,让KVM的内存虚拟化更加的高效,我们从最初的软件虚拟化的方式介绍。

软件虚拟化方式实现
  第一层转换,由GVA->GPA的转换和传统的转换关系一样,通过查找CR3然后进行页表查询,找到对应的GPA,GPA到HVA的关系由qemu-kvm负责维护,我们在第二章KVM启动过程的demo里面就有介绍到怎样给KVM映射内存,通过mmap的方式把HV的内存映射给Guest。
DSC0002.png

  

struct kvm_userspace_memory_region region = {  .slot = 0,
  .guest_phys_addr = 0x1000,
  .memory_size = 0x1000,
  .userspace_addr = (uint64_t)mem,
  
};
  

  可以看到,qemu-kvm的kvm_userspace_memory_region结构体描述了guest的物理地址起始位置和内存大小,然后描述了Guest的物理内存在HV的映射userspace_addr,通过多个slot,可以把不连续的HV的虚拟地址空间映射给Guest的连续的物理地址空间。
DSC0003.png

  软件模拟的虚拟化方式由qemu-kvm来负责维护GPA->HVA的转换,然后再经过一次HVA->HPA的方式,从过程上来看,这样的访问是很低效的,特别是在当GVA到GPA转换时候产生缺页中断,这时候产生一个异常Guest退出,HV捕获异常后计算出物理地址(分配新的内存给Guest),然后重新Entry。这个过程会可能导致频繁的Guest退出,且转换过程过长。于是KVM使用了一种叫做影子页表的技术。

影子页表的虚拟化方式
  影子页表的出现,就是为了减少地址转换带来的开销,直接把GVA转换到HVP的技术。在软件虚拟化的内存转换中,GVA到GPA的转换通过查询CR3寄存器来完成,CR3保存了Guest中的页表基地址,然后载入MMU来做地址转换。
  
在加入了影子页表的技术后,当访问到CR3寄存器的时候(可能是由于Guest进程后导致的),KVM捕获到这个操作,CPU虚拟化章节 EXIT_REASON_CR_ACCESS,qemu-kvm通过载入特俗的CR3和影子页表来欺骗Guest这个就是真实的CR3,后面的操作就和传统的访问内存的方式一致,当需要访问物理内存的时候,只会经过一层的影子页表的转换。
DSC0004.png

  影子页表由qemu-kvm进程维护,实际上就是一个Guest的页表到宿主机页表的映射,每一级的页表的hash值对应到qemu-kvm中影子页表的一个目录。在初次GVA->HPA的转换时候,影子页表没有建立,此时Guest产生缺页中断,和传统的转换过程一样,经过两次转换(VA->PA),然后影子页表记录GVA->GPA->HVA->HPA。这样产生GVA->GPA的直接关系,保存到影子页表中。
DSC0005.png

  影子页表的引入,减少了GVA->HPA的转换过程,但是坏处在于qemu-kvm需要为Guest的每个进程维护一个影子页表,这将带来很大的内存开销,同时影子页表的建立是很耗时的,如果Guest进程过多,将导致频繁的影子页表的导入与导出,虽然用了cache技术,但是还是软件层面的,效率并不是最好,所以Intel和AMD在此基础上提供了硬件虚拟化技术。

EPT硬件加速的虚拟化方式
DSC0006.png

  
EPT(extended page table)可以看做一个硬件的影子页表,在Guest中通过增加EPT寄存器,当Guest产生了CR3和页表的访问的时候,由于对CR3中的页表地址的访问是GPA,当地址为空时候,也就是Page fault后,产生缺页异常,如果在软件模拟或者影子页表的虚拟化方式中,此时会有VM退出,qemu-kvm进程接管并获取到此异常。但是在EPT的虚拟化方式中,qemu-kvm忽略此异常,Guest并不退出,而是按照传统的缺页中断处理,在缺页中断处理的过程中会产生EXIT_REASON_EPT_VIOLATION,Guest退出,qemu-kvm捕获到异常后,分配物理地址并建立GVA->HPA的映射,并保存到EPT中,将EPT载入到MMU,下次转换时候直接查询根据CR3查询EPT表来完成GVA->HPA的转换。以后的转换都由硬件直接完成,大大提高了效率,且不需要为每个进程维护一套页表,减少了内存开销。
  
在笔者的测试中,Guest和HV的内存访问速率对比为3756MB/s对比4340MB/s。可以看到内存访问已经很接近宿主机的水平了。

总结
  KVM内存的虚拟化就是一个将虚拟机的虚拟内存转换为宿主机物理内存的过程,Guest使用的依然是宿主机的物理内存,只是在这个过程中怎样减少转换带来的开销成为优化的主要点。
  
KVM经过软件模拟->影子页表->EPT的技术的进化,效率也越来越高。

运维网声明 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-387534-1-1.html 上篇帖子: 关于Linux虚拟化技术KVM的科普 下篇帖子: 关于Linux虚拟化技术KVM的科普 科普三(From OenHan)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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