今天分享的文章是发表在ATC’17的《Optimizing the Design and Implementation of the Linux ARM Hypervisor》,作者是来自哥伦比亚大学的Christoffer Dall等人。在ARMv8.2之前,ARM架构对于虚拟化的支持并不好,KVM所在Host OS与虚拟机共用同一个内核态,这导致了KVM在ARM架构下的性能较差。在这篇文章中,作者利用ARM的硬件特性对Linux上的KVM进行了优化,使其性能得到了大幅度提高。
1 Introduction
目前市面上的Hypervisor可以分为两类:Type 1和Type 2。Type 1类型的Hypervisor可以直接在主机的物理硬件上运行,而Type 2类型的Hypervisor则需要Host OS才能运行。不管是Type 1还是Type 2类型的Hypervisor,它们都支持guest VM OS在kernel mode中运行,只有在进行一些敏感操作时,Hypervisor才会对guest VM进行接管。
从guest VM切换到Hypervisor时,因为它们共享kernel mode的寄存器,所以需要对上下文进行保存和恢复。在X86架构上,Intel提供了VMX的硬件特性。通过VMX,只需一条指令就可以完成上下文的保存与切换。但是在ARM架构上,并没有提供一个硬件机制来自动完成这件事。与之相反,它依赖软件来对每个需要保存和恢复的寄存器进行处理。这大大增加了切换时的时间开销。
在这篇文章,作者主要考虑对Type 2类型的Hypervisor进行性能优化。利用了ARM对于Type 2类型的Hypervisor的虚拟化支持,作者对重新设计并实现了KVM。和以前的KVM相比,重新设计过的KVM有以下几个优点:
1.从guest VM到Hypervisor的切换不再需要保存和恢复kernel mode的寄存器状态。2.Host OS可以在需要时可以直接对guest VM使用的硬件状态进行管理。3.KVM和Host可以在相同的Exception Level下运行。KVM可以直接利用Host OS的功能,同时对ARM硬件虚拟化功能进行配置。通过这种,可以降低KVM的代码复杂性并提高其性能。
2 Background
2.1 ARM虚拟化支持
为了支持虚拟化,ARM引入了一个新的异常等级EL2。当VM执行敏感操作或者需要访问IO时,则会从EL0或者EL1陷入到EL2。为了隔离不同的虚拟机,ARM还引入了硬件特性VE,也就是stage 2 translation。通过额外增加一层地址转换,Hypervisor可以在ARM上实现内存虚拟化。
除了VE之外,ARMv8.1引入了新的硬件特性VHE用来更好地支持Type 2类型的Hypervisor。VHE主要提供了三个特性:
1.在EL2增加了额外的寄存器,提供了与EL1寄存器相同的功能。这使得操作系统可以在没有经过修改的情况下在EL2中运行。2.VHE支持EL0中的应用程序与EL2中运行的Host OS直接交互。这些程序运行在user mode,使用EL0中的虚拟内存。3.VHE将EL2的页表格式更改为与EL1相同的格式,从而避免了更改现有kernel的页表管理代码以支持不同的格式。
2.2 KVM/ARM
在未引入VHE之前,EL2不能被用于运行现有的未修改操作系统内核。由于EL2有自己独立的寄存器集,并且地址空间独立且有限,这使得EL2与EL1不兼容。因此KVM无法直接在EL2上运行。为了使得KVM能够在ARM上正常运行,KVM被拆成了两部分,一部分运行在EL1,另一部分则运行在EL2。大多数Hypervisor的功能在EL1中运行,作为Host OS的一部分,可以完全访问硬件,另一部分则在EL2中运行,被称为lowvisor。由于ARM不像X86那样有特殊的硬件机制可以便捷地来保存和恢复CPU的状态,EL1中的KVM需要向EL2中的lowvisor发出一个hypercall-to-trap,让它通过软件的方式逐个保存和恢复所有寄存器和CPU的配置状态。在将CPU的状态切换为对应的VM后,lowvisor将执行指令eret进入到VM。当VM陷入到EL2时,lowvisor再次保存并恢复CPU的整个状态,并将EL0和EL1的执行上下文切换回Hypervisor。
3 Hypervisor Redesign
首先,作者重新设计了KVM在ARM上的架构,以避免在VM和Hypervisor之间进行切换时进行上下文的保存与恢复。如图所示,我们可以发现KVM直接在EL2中运行,当它需要在物理CPU上运行VM的VCPU时,它可以将VM的EL1状态直接加载到CPU寄存器中,无需再对Host OS的寄存器进行保存。
其次,新的设计避免了在VM和Hypervisor之间进行切换时,需要启用和禁用虚拟化功能。在之前的设计中,为了Host OS能够完全访问底层硬件,在进入Hypervisor时必须禁用虚拟化功能,但在运行VM时必须启用虚拟化功能以便限制VM对硬件的访问。由于虚拟化功能只对运行在EL0和EL1的软件有效,因此对于运行在EL2的Host OS已不再有效。对于如今的KVM而言,在退出VM时,无需禁用虚拟化功能。
最后,新的设计可以避免在EL1和EL2之间进行数据传递。前文提到,最初的KVM在ARM上被分为了两部分。虽然大部分管理程序功能都是在EL1中运行的管理程序OS内核中实现的,但是在一些方面仍然需要在EL2中运行程序来对硬件进行编程。这就导致了KVM会对数据处理处理两次,一次在EL1中将数据写入中间数据结构,一次在EL2中,根据中间数据结构对硬件进行编程。除此之外,EL1和EL2的地址空间不同,对中间数据结构的访问会导致TLB miss,这使得性能进一步下降。但是通过借助VHE,KVM可以完整地在EL2中运行,已不再需要中间数据结构来进行信息传递。
4 Evaluation
ARM表示为引入VHE的KVM;ARM EL2表示将KVM在EL2中运行,但是并未进行任何优化;ARM EL2 OPT表示经过优化的ARM EL2。从实验结果中我们可以发现,作者重新设计并优化的KVM的性能得到了较大的提升。
原文始发于微信公众号(COMPASS Lab):[论文分享] | 优化ARM Hypervisor的设计与现实