物联网市场的应用场景日益复杂,越来越多的上网设备需要支持更多的硬件资源、操作系统、软件工具及应用程序,现有的解决方案显然无法为数量庞大的物联网设备提供相应的灵活性,这使开发者们面临巨大的设计压力。虚拟化技术是解决这些问题的关键。不过,现有的虚拟化解决方案并不能满足物联网开发的轻量级和灵活性的特殊要求。为了满足当前物联网市场的发展趋势,Linux基金会推出了开源项目—ACRN
ACRN到底具有哪些强大的功能,它又是怎么实现的?今天我们就从架构到应用对ACRN进行详细分析,让开发者们快速上手使用ACRN进行产品设计。
ACRN是一个专为嵌入式设备设计的hypervisor,包括如下两部分:一套hypervisor的参考软件和架构,通过虚拟机监视器(Virtual Machine Manager)可以在同一个物理硬件上安全地同时运行多个操作系统。另外,它还为设备虚拟化模拟定义了一套参考设计框架,称为“ACRN设备模型”。
ACRN hypervisor是一个Type-I的hypervisor,可以直接运行在物理硬件上,适用于各种物联网和嵌入式设备解决方案。ACRN hypervisor解决了当前数据中心hypervisor和partitioning hypervisor之间存在的差距。ACRN hypervisor设计时把系统分为不同的功能域,并为物联网和嵌入式设备精心挑选的用户操作系统进行共享优化。
汽车应用案例
ACRN hypervisor的一个有趣的案例是用于汽车场景。ACRN hypervisor可以用于构建软件定义驾驶舱(SDC)或者车载娱乐系统(IVE)。作为参考实现,ACRN可以为嵌入式hypervisor厂商的解决方案提供一个很好的基础,以及一套I/O设备虚拟化的参考设计。
ACRN hypervisor的一个有趣的案例是用于汽车场景。ACRN hypervisor可以用于构建软件定义驾驶舱(SDC)或者车载娱乐系统(IVE)。作为参考实现,ACRN可以为嵌入式hypervisor厂商的解决方案提供一个很好的基础,以及一套I/O设备虚拟化的参考设计。
在这种场景下,汽车SDC系统由仪表盘(IC)系统、车载信息娱乐系统(IVI)和一个或多个后座娱乐系统(RSE)组成。为了整体系统安全性考虑,每个系统都作为独立的虚拟机运行。
仪表盘系统(IC)用于显示和驾驶员相关的车辆的驾驶操作信息,如:
• 汽车的速度、燃油、行驶里程和其它驾驶信息;
• 投影在挡风玻璃上的抬头显示,用以警告缺油或胎压报警;
• 显示后视摄像头影像和车身的周边摄像头信息,用于辅助停车;
• 汽车的速度、燃油、行驶里程和其它驾驶信息;
• 投影在挡风玻璃上的抬头显示,用以警告缺油或胎压报警;
• 显示后视摄像头影像和车身的周边摄像头信息,用于辅助停车;
车载娱乐系统(IVI)的功能包括:
• 导航系统、收音机和其它娱乐系统;
• 连接到移动设备,可以打电话,播放音乐或者通过语音识别来控制应用程序;
• 通过手势识别或触控进行交互;
• 导航系统、收音机和其它娱乐系统;
• 连接到移动设备,可以打电话,播放音乐或者通过语音识别来控制应用程序;
• 通过手势识别或触控进行交互;
后座娱乐系统(RSE)可以运行:
• 娱乐系统;
• 虚拟办公;
• 连接到前排座椅的IVI系统和移动设备(云连接);
• 连接到移动设备,可以打电话,播放音乐或者通过语音识别来控制应用程序;
• 通过手势识别或触控进行交互;
• 娱乐系统;
• 虚拟办公;
• 连接到前排座椅的IVI系统和移动设备(云连接);
• 连接到移动设备,可以打电话,播放音乐或者通过语音识别来控制应用程序;
• 通过手势识别或触控进行交互;
ACRN hypervisor可以支持Linux*和Android*虚拟机作为用户操作系统(UOS),UOS由ACRN hypervisor进行管理。开发者和OEM厂商可以在ACRN hypervisor之上运行自己的虚拟机,以及IC、IVI和RSE VM。Service OS是作为VM0运行(在Xen* hypervisor中被称为Dom0,在KVM* hypervisor中被称为Host OS),User OS用户操作系统作为VM1运行(也被称为DomU)。
注:Android*虚拟机的支持将在未来版本发布。
注:Android*虚拟机的支持将在未来版本发布。
图1显示了一个使用ACRN hypervisor的实例框图。
图1:SOS和UOS运行在ACRN hypervisor之上
从ACRN hypervisor的架构图中可以看到:
• ACRN hypervisor直接位于bootloader之上,因而具备快速启动的能力;
• 部分资源进行partitioning,以确保安全关键性应用和非安全关键业务可以共存在同一平台上;
• 丰富的I/O设备虚拟化提供在多个VM之间的I/O设备共享,从而提供全面的用户体验;
• 通过高效的虚拟化,一个SoC可以支持多个操作系统同时运行;
• ACRN hypervisor直接位于bootloader之上,因而具备快速启动的能力;
• 部分资源进行partitioning,以确保安全关键性应用和非安全关键业务可以共存在同一平台上;
• 丰富的I/O设备虚拟化提供在多个VM之间的I/O设备共享,从而提供全面的用户体验;
• 通过高效的虚拟化,一个SoC可以支持多个操作系统同时运行;
图1中的黄色部分是ACRN项目的软件栈。该架构框图中列出的某些功能还没有完全实现,欢迎社区共同参与开发实现。另外,图中的其他模块来自于别的开源项目,这里仅供参考。
例如,Service OS和Guest Linux来源于https://clearlinux.org上的Clear Linux项目,而未来Guest Android的支持将会来自https://01.org/android-ia项目。
当前ACRN所支持的功能列表,请参照发布说明。
许可证
ACRN hypervisor和ACRN Device Model软件采用的都是自由许可证的BSD-3-Clause,它允许以“源代码和二进制再次发布和使用,无论是否进行了修改”, 许可证中也注明了完整版权声明和免责声明。
ACRN hypervisor和ACRN Device Model软件采用的都是自由许可证的BSD-3-Clause,它允许以“源代码和二进制再次发布和使用,无论是否进行了修改”, 许可证中也注明了完整版权声明和免责声明。
ACRN Device Model, Service OS, and User OS
为了使ACRN hypervisor代码尽可能精悍且高效,用于实现I/O设备共享的device model代码运行在Service OS中而非ACRN Hypervisor。哪些I/O设备被共享以及其实现细节将在下面的pass-through章节具体介绍。
为了使ACRN hypervisor代码尽可能精悍且高效,用于实现I/O设备共享的device model代码运行在Service OS中而非ACRN Hypervisor。哪些I/O设备被共享以及其实现细节将在下面的pass-through章节具体介绍。
Service OS在所有虚拟机里,以最高优先权运行,以满足那些对时间响应要求很高的需求和系统服务质量的需求(QoS)。具体到Service OS中的任务(task),他们的优先级则有高有低。例如响应User OS请求的回调函数,其运行在Service OS的软件(或者mediator)就会继承User OS的优先级。另外,在Service OS中还有一些在后台运行的任务也是低优先级。
在上述的车载系统示例中,User OS是驾驶控制和车内娱乐的中心枢纽。它能提供收音机和各种娱乐选项、车内空调和通风控制、车辆导航显示等支持。它可以让第三方设备使用USB、蓝牙或者WiFi等连接技术与车载系统进行交互,例如:Android Auto* 或者 Apple CarPlay*, 还能提供许多其它功能。
启动步骤
在图2中,我们展示了在一个采用英特尔架构平台的NUC上使用UEFI验证启动的步骤。
在图2中,我们展示了在一个采用英特尔架构平台的NUC上使用UEFI验证启动的步骤。
启动引导顺序执行如下:
1 UEFI验证和启动ACRN hypervisor和Service OS的引导加载程序;
2 UFEI(或Service OS的引导加载程序)验证并启动Service OS内核;
3 Service OS的内核通过dm-verity验证并且加载ACRN Device Model和虚拟引导加载程序;
4 虚拟引导加载程序启动用户端的验证启动进程;
1 UEFI验证和启动ACRN hypervisor和Service OS的引导加载程序;
2 UFEI(或Service OS的引导加载程序)验证并启动Service OS内核;
3 Service OS的内核通过dm-verity验证并且加载ACRN Device Model和虚拟引导加载程序;
4 虚拟引导加载程序启动用户端的验证启动进程;
ACRN Hypervisor架构
ACRN hypervisor是Type 1的虚拟机管理程序,能够直接运行在硬件系统上。它是一个混合的VMM架构,采用一个运行在特权级的Service OS来管理和协调I/O设备的使用。它能支持多个用户虚拟机,其中每个虚拟机都可以运行Linux或者安卓操作系统作为用户操作系统。
ACRN hypervisor是Type 1的虚拟机管理程序,能够直接运行在硬件系统上。它是一个混合的VMM架构,采用一个运行在特权级的Service OS来管理和协调I/O设备的使用。它能支持多个用户虚拟机,其中每个虚拟机都可以运行Linux或者安卓操作系统作为用户操作系统。
在虚拟机内运行的操作系统是与其它虚拟机内的系统或应用程序相互隔离的,从而缩小了潜在的被攻击可能性,最大限度地减小安全隐患。当然由于系统运行在虚拟机内也可能会给其应用程序的运行带来额外的延迟。
图3显示了ACRN hypervisor、车载系统中的Instrumental Cluster (IC) VM和Service VM一起协同工作的架构图。Service OS(SOS)负责包括平台设备在内的大部分设备的管理,并提供I/O的协调功能。某些PCIe设备可以通过VM配置直通给User OS使用。IC应用程序和虚拟机特定的应用程序都运行在SOS中,例如:ACRN device model和ACRN VM管理器。
ACRN hypervisor内还有ACRN虚机管理器,用来收集User OS的运行信息,并控制用户虚拟机的开始、停止和暂停,还能暂停或者恢复执行单个虚拟CPU。
图3 ACRN Hypervisor 架构图
ACRN hypervisor采用了英特尔虚拟化技术(Intel VT),其运行在虚拟机扩展模式(VMX)的root模式下,也称为主机模式或VMM模式。其他所有的用户虚拟机包括UOS和SOS都运行在VMX non-root模式或guest模式下。(以下为了简略,我们将继续使用术语VMM模式和guest模式)。
VMM模式下有4种权限的ring模式,但ACRN hypervisor仅在ring 0的特权模式下运行,其余ring 1-3并未使用。运行在guest模式下的用户系统(包括SOS和UOS)也有自己的4个ring模式(ring 0-3)。用户系统的内核运行在guest模式下的ring 0,而用户系统的应用程序则在guest模式下运行于ring 3(ring 1和ring 2一般不被商业操作系统所使用)。
图4 VMX 简介
如图4所示,VMM模式和guest模式通过VM Exit和VM Entry进行切换。当引导加载程序将控制权交给ACRN hypervisor时,处理器还未启动VMX模式。ACRN hypervisor首先需要通过VMXON指令启用VMX模式。启用VMX后,处理器处于VMM模式,它可以通过VM resume指令进入guest模式(或者通过第一次VM launch指令),然后可以通过处理器的VM exit事件回到VMM模式。一般处理器会在响应某些指令和事件时发生VM exit。
在guest模式下,处理器的执行是由一个虚拟机控制结构(VMCS)所控制的。VMCS包含了虚机状态(在VM Entry时加载并在VM Exit时保存),主机状态(在VM exit时加载),以及虚机的控制执行。ACRN hypervisor为每个虚拟CPU创建了一个VMCS数据结构,并使用该VMCS来控制运行在guest模式下处理器的行为。
当虚机执行到一个敏感指令时,就会触发一次定义在VMCS配置中的VM exit事件。当VM exit发生后,系统的控制权就交给了ACRN hypervisor。ACRN hypervisor会模拟虚机的指令(如果VM exit的原因是由于指令权限问题),然后恢复虚机继续执行它的下一条指令,或者根据VM exit的原因进行相关处理(例如,一个虚机的存储页面需要建立映射关系),然后恢复虚机重新执行该条指令。
需要注意的是用于VMM模式的地址空间和用于guest模式的地址空间是不同的。guest模式和VMM模式下使用不同的内存映射表,因此虚机是无法访问ACRN hypervisor的。ACRN hypervisor使用EPT来映射虚机地址,虚机页表会将虚机的线性地址映射到虚机的物理地址, EPT表则将虚机的物理地址映射到机器物理地址或主机物理地址(HPA)。
ACRN Device Model Architecture
因为系统设备可能需要在不同的虚机之间被共享,虚机内应用程序(和操作系统)要对这些共享设备进行访问就需要借助设备模拟。一般来说,设备模拟有三种架构:
因为系统设备可能需要在不同的虚机之间被共享,虚机内应用程序(和操作系统)要对这些共享设备进行访问就需要借助设备模拟。一般来说,设备模拟有三种架构:
• 第一种架构被称为hypervisor中的设备模拟,这是在VMware*工作站产品(一个基于操作系统的hypervisor)中实现的设备模拟方式。在这种方式中,hypervisor负责模拟需要在各个虚机操作系统之间共享的常见设备,其中包括:虚拟磁盘、虚拟网络适配器和其它必要的平台资源。
• 第二种架构称为用户空间的设备模拟。顾名思义,不是将设备模拟的实现嵌入到hypervisor中,而是将其放在一个用户空间的应用程序中实现。比如被各种独立的hypervisor所使用的QEMU就提供了此类的设备模拟方式。这种架构的优势在于设备模拟的实现不依赖于hypervisor,所以其它hypervisor可以重用改实现。甚至它还可以做任意设备的模拟,而不必担心其功能的实现会影响hypervisor(其在特权模式下运行)。
• 第三种架构则是从基于hypervisor的设备模拟改变而来的半虚拟化驱动程序。该架构一开始是在XEN项目中引入的,其中hypervisor提供物理设备驱动,每个虚机操作系统则需要安装一个与能与物理驱动配合使用的hypervisor感知的驱动程序。
在以上讨论的设备模拟架构中,共享设备都需要付出代价。因为不管设备模拟是在hypervisor中,还是在每个虚机内的用户空间中,都存在相应的系统开销。不过只要系统设备需要被多个虚机操作系统共享,这种开销就是值得的。反之如果设备不需要被共享,那么就可以使用更有效的方法来访问设备,例如使用“直通”。
看完以上的分析,你是否对ACRN有了更深入的了解?也是否有更多问题急需解答? 不用着急,我们将在下期中继续讲解各种技术细节,例如ACRN设备模块架构、设备pass through, ACRN I/O mediator, Virtio框架结构等一一为你展示。
ACRN的设备模块
在ACRN中,每个User OS(简称UOS)都需要有一个ACRN设备模型与之对应。ACRN设备模型首先为UOS初始化虚拟硬件平台(包括初始化VCPU状态、分配并初始化内存、初始化UOS启动脚本中所指定的虚拟设备)、加载guest平台固件文件或guest操作系统内核文件等,并最终通过调用ACRN hypervisor提供的服务去执行guest指令。
在ACRN中,每个User OS(简称UOS)都需要有一个ACRN设备模型与之对应。ACRN设备模型首先为UOS初始化虚拟硬件平台(包括初始化VCPU状态、分配并初始化内存、初始化UOS启动脚本中所指定的虚拟设备)、加载guest平台固件文件或guest操作系统内核文件等,并最终通过调用ACRN hypervisor提供的服务去执行guest指令。
ACRN设备模型是运行在Service OS(简称SOS)上的应用程序,其架构如图5所示。
图5 ACRN 设备模块
在ACRN中, I/O虚拟化主要依赖于以下三部分的协同工作:
1)设备仿真
2)I/O请求处理
3)VHM(Virtio and Hypervisor service Module)。
1)设备仿真
2)I/O请求处理
3)VHM(Virtio and Hypervisor service Module)。
设备仿真:
设备仿真指的是一系列I/O设备仿真例程,用来模拟不同种类的设备,比如PCI总线设备、ACPI设备等。这些设备仿真例程均会被注册到ACRN设备模型中,由ACRN设备模型中的I/O调度器进行调度和分发。当UOS产生I/O设备访问请求时,I/O调度器会根据请求的I/O地址,PIO或者MMIO,进一步调用具体设备的仿真例程。
I/O请求(简称IOREQ)处理:
参照以下ACRN-I/O-mediator
设备仿真指的是一系列I/O设备仿真例程,用来模拟不同种类的设备,比如PCI总线设备、ACPI设备等。这些设备仿真例程均会被注册到ACRN设备模型中,由ACRN设备模型中的I/O调度器进行调度和分发。当UOS产生I/O设备访问请求时,I/O调度器会根据请求的I/O地址,PIO或者MMIO,进一步调用具体设备的仿真例程。
I/O请求(简称IOREQ)处理:
参照以下ACRN-I/O-mediator
VHM:
VHM(Virtio and Hypervisor service Module)模块作为ACRN hypervisor和设备模型之间的桥梁,为设备模型提供必要的服务。VHM运行在Service OS中,以内核模块的形式存在,其具体的服务流程,如下所述:
VHM(Virtio and Hypervisor service Module)模块作为ACRN hypervisor和设备模型之间的桥梁,为设备模型提供必要的服务。VHM运行在Service OS中,以内核模块的形式存在,其具体的服务流程,如下所述:
1 ACRN hypervisor通过中断的方式通知VHM新的IOREQ到来;
2 VHM首先将IOREQ标记为“正在处理”,同时将其发送给VHM的用户(如设备模型、gvt-g、VBS-K等)做进一步处理。之后,VHM可以处理新的IOREQ;
3 实际对IOREQ进行处理的可以是运行在SOS用户态的ACRN设备模型,也可以是运行在SOS内核态中的其他设备模型,如gvt-g和VBS-K。一旦IOREQ被处理完成,VHM将被通知(内核态直接通过函数调用方式通知,而用户态则通过IOCTL的方式通知),之后VHM通过hypercall的方式,进一步通知ACRN hypervisor该IOREQ已经处理完成。
用户态程序:ACRN设备模型;
内核态模块:VHM、VBS-K、gvt-g等;
内核态模块:VHM、VBS-K、gvt-g等;
设备直通
总体上讲,设备直通是为了将指定设备排他性提供给某个客户操作系统独立使用。
图6 设备直通
通过设备直通可以实现几乎原生的性能。在不需要在多个虚拟机中共享同一个设备的情况下,如系统中有多块物理设备,设备直通对于某些高I/O需求的设备来说是最佳选择,因为通过hypervisor(无论是在hypervisor中还是在用户空间中)虚拟设备会产生额外的性能下降。
除了性能角度考量外,有些设备先天不能被用在多个虚拟共享环境中,如USB device模式的xDCI端口。对于这类设备,ACRN中则直接采用设备直通的方式供客户操作系统使用。
除了性能角度考量外,有些设备先天不能被用在多个虚拟共享环境中,如USB device模式的xDCI端口。对于这类设备,ACRN中则直接采用设备直通的方式供客户操作系统使用。
设备直通的硬件支持
英特尔目前的处理器架构使用VT-d为设备直通提供支持。VT-d将客户平台物理地址映射到本地平台机器物理地址,从而客户操作系统能够通过访问客户平台物理地址进而访问到本地平台的物理硬件。在这个过程中,VT-d负责设备的发访问和保护,而客户平台操作系统只需像非虚拟化环境中一样,直接访问设备。除此之外,VT-d还能防止物理设备恶意访问属于其他VM或者hypervisor的内存,从而能够提高安全性。
此外,在ACRN项目中,设备主要使用MSIx/MSI中断,而不是传统的基于中断pin的方式通知guest。从而带来的好处在于不仅能够很好地处理来自于多个VM多个中断的情况,而且能够保证中断源的隔离。
英特尔目前的处理器架构使用VT-d为设备直通提供支持。VT-d将客户平台物理地址映射到本地平台机器物理地址,从而客户操作系统能够通过访问客户平台物理地址进而访问到本地平台的物理硬件。在这个过程中,VT-d负责设备的发访问和保护,而客户平台操作系统只需像非虚拟化环境中一样,直接访问设备。除此之外,VT-d还能防止物理设备恶意访问属于其他VM或者hypervisor的内存,从而能够提高安全性。
此外,在ACRN项目中,设备主要使用MSIx/MSI中断,而不是传统的基于中断pin的方式通知guest。从而带来的好处在于不仅能够很好地处理来自于多个VM多个中断的情况,而且能够保证中断源的隔离。
设备直通的hypervisor支持
较新的英特尔处理器架构均支持VT-d,因此各主流hypervisor(Xen和KVM)均可以基于VT-d实现设备直通的功能。ACRN同样基于VT-d实现设备直通的功能。
ACRN虚拟I/O设备
图7 展示了ACRN中访问一个虚拟I/O所经历的流程。
图7 I/O虚拟流程(Port IO)
以下是图7中的编号项目:
1、当guest操作系统执行I/O指令(PIO 或 MMIO)时,VM-Exit发生,ACRN hypervisor获得处理器控制权,首先会判断虚拟机执行退出的原因。在我们的例子中,VM-Exit是因为guest中发生了PIO访问,退出原因的号码为VMX_EXIT_REASON_IO_INSTRUCTION。
2、除了根据VM-Exit的原因号码,ACRN hypervisor还会对产生VM-Exit的指令进行译码。在我们的例子中,hypervisor会注意到是PIO指令(例如:in AL, 20h)。接下来,hypervisor将译码得到的相关信息(包括PIO访问、访问字节数、读/写方式、目标寄存器等)放到与ACRN VHM、ACRN设备模型共享的物理页面之中,然后以中断的方式通知SOS/VHM去做进一步处理。
3、SOS中的VHM接收到中断后,查询该IOREQ有关的所有信息。
4、VHM首先会检查是否应该由内核态的设备模型来处理该IOREQ,如果是,那么相应的内核模块之前注册的callback函数会被VHM调用。否则,如果没有内核态设备模型来处理IOREQ,那么VHM则会将该IOREQ保留在共享页面中,并唤醒ACRN设备模型对该IOREQ进行处理。
5、ACRN设备模型采用与VHM相同的机制对IOREQ进行处理。设备模型的I/O执行线程会首先查询IOREQ具体的信息,同时检查是否有设备仿真模块实现了该IOREQ对应的逻辑。如果有相应的模块,那么该模块对应的callback函数将会被调用。
6、ACRN设备模型完成设备模拟仿真后(本示例中是对端口IO 20h的访问,uDev1将结果保存到共享页面(示例中保存在AL寄存器)。
7、完成相应IOREQ的模拟和仿真后,ACRN设备模型通过VHM的API将控制权返回给ACRN hypervisor。
8、ACRN hypervisor得知IOREQ已经处理完成,则会结果保存到VCPU的相应寄存器中。
9、ACRN hypervisor更新完VCPU寄存器后,进一步更新IP地址寄存器指向下一条guest指令,同时重启guest的执行。
针对guest中MMIO访问的处理,与上面例子中的PIO访问处理类似,除了VM-Exit的原因不同:MMIO对应的VM-Exit原因代码是VMX_EXIT_REASON_EPT_VIOLATION。
1、当guest操作系统执行I/O指令(PIO 或 MMIO)时,VM-Exit发生,ACRN hypervisor获得处理器控制权,首先会判断虚拟机执行退出的原因。在我们的例子中,VM-Exit是因为guest中发生了PIO访问,退出原因的号码为VMX_EXIT_REASON_IO_INSTRUCTION。
2、除了根据VM-Exit的原因号码,ACRN hypervisor还会对产生VM-Exit的指令进行译码。在我们的例子中,hypervisor会注意到是PIO指令(例如:in AL, 20h)。接下来,hypervisor将译码得到的相关信息(包括PIO访问、访问字节数、读/写方式、目标寄存器等)放到与ACRN VHM、ACRN设备模型共享的物理页面之中,然后以中断的方式通知SOS/VHM去做进一步处理。
3、SOS中的VHM接收到中断后,查询该IOREQ有关的所有信息。
4、VHM首先会检查是否应该由内核态的设备模型来处理该IOREQ,如果是,那么相应的内核模块之前注册的callback函数会被VHM调用。否则,如果没有内核态设备模型来处理IOREQ,那么VHM则会将该IOREQ保留在共享页面中,并唤醒ACRN设备模型对该IOREQ进行处理。
5、ACRN设备模型采用与VHM相同的机制对IOREQ进行处理。设备模型的I/O执行线程会首先查询IOREQ具体的信息,同时检查是否有设备仿真模块实现了该IOREQ对应的逻辑。如果有相应的模块,那么该模块对应的callback函数将会被调用。
6、ACRN设备模型完成设备模拟仿真后(本示例中是对端口IO 20h的访问,uDev1将结果保存到共享页面(示例中保存在AL寄存器)。
7、完成相应IOREQ的模拟和仿真后,ACRN设备模型通过VHM的API将控制权返回给ACRN hypervisor。
8、ACRN hypervisor得知IOREQ已经处理完成,则会结果保存到VCPU的相应寄存器中。
9、ACRN hypervisor更新完VCPU寄存器后,进一步更新IP地址寄存器指向下一条guest指令,同时重启guest的执行。
针对guest中MMIO访问的处理,与上面例子中的PIO访问处理类似,除了VM-Exit的原因不同:MMIO对应的VM-Exit原因代码是VMX_EXIT_REASON_EPT_VIOLATION。
Virtio框架架构
Virtio是一种通用的面向虚拟设备的抽象,可以应用在任何hypervisor中。在ACRN参考设计中,我们的Virtio实现兼容Virtio标准规范0.9和1.0。带来的好处是,对于虚拟设备的实现,虚拟环境和客户平台可以复用一套直观、高效、标准和可扩展的机制,而无需根据每个环境或者操作系统进行定制。
Virtio提供一个通用的前端/后端驱动程序框架,它不仅标准化virtio设备的访问接口,而且还增加了不同的虚拟化平台上的代码重用。
Virtio是一种通用的面向虚拟设备的抽象,可以应用在任何hypervisor中。在ACRN参考设计中,我们的Virtio实现兼容Virtio标准规范0.9和1.0。带来的好处是,对于虚拟设备的实现,虚拟环境和客户平台可以复用一套直观、高效、标准和可扩展的机制,而无需根据每个环境或者操作系统进行定制。
Virtio提供一个通用的前端/后端驱动程序框架,它不仅标准化virtio设备的访问接口,而且还增加了不同的虚拟化平台上的代码重用。
图8 Virtio 架构
为了更好地理解Virtio,尤其是它在ACRN项目中的使用,下面列举几个Virtio的关键概念:
Virtio前端驱动程序
Virtio采用了前端-后端架构,分别为前端和后端Virtio驱动程序提供一个简单又灵活的框架。Virtio前端驱动框架提供了前端Virtio API来配置硬件、传递消息、提交请求、通知后端Virtio驱动程序等。因此,Virtio前端驱动程序很容易实现,并且性能与设备模拟仿真相比有较大提升。
Virtio采用了前端-后端架构,分别为前端和后端Virtio驱动程序提供一个简单又灵活的框架。Virtio前端驱动框架提供了前端Virtio API来配置硬件、传递消息、提交请求、通知后端Virtio驱动程序等。因此,Virtio前端驱动程序很容易实现,并且性能与设备模拟仿真相比有较大提升。
后端Virtio驱动程序
与Virtio前端驱动程序类似,Virtio后端驱动程序运行在宿主平台(内核态或者用户态)。Virtio后端驱动程序处理来自于前端驱动程序的请求,并按需将请求进一步发送到本地设备驱动程序。一旦请求被Virtio后端驱动程序处理完成,后端驱动程序就会通知前端驱动程序“请求已完成”。
与Virtio前端驱动程序类似,Virtio后端驱动程序运行在宿主平台(内核态或者用户态)。Virtio后端驱动程序处理来自于前端驱动程序的请求,并按需将请求进一步发送到本地设备驱动程序。一旦请求被Virtio后端驱动程序处理完成,后端驱动程序就会通知前端驱动程序“请求已完成”。
直观:Virtio设备复用已有设备总线
Virtio复用已有设备总线,而不是创建全新类型的设备总线,带来的好处是Virtio前端和后端驱动可以直接利用已有的代码进行交互。例如,Virtio前端驱动程序可以直接读/写虚拟设备(由Virtio后端驱动程序虚拟)的寄存器,同时虚拟设备(由Virtio后端驱动程序虚拟)可以直接以中断的方式通知前端驱动程序事件的发生。目前,Virtio标准规范定义了几种总线结果,如PCI/PCIe总线、MMIO总线、CCW总线等。目前ACRN项目只支持PCI/PCIe总线。
高效:鼓励批处理操作
批处理操作和延迟通知对于实现高性能I/O非常重要,因为Virtio前端和后端驱动程序之间的通知会导致代价高昂的VM-Exit等。因此应当尽可能批量处理数据,同时减少事件的通知。
批处理操作和延迟通知对于实现高性能I/O非常重要,因为Virtio前端和后端驱动程序之间的通知会导致代价高昂的VM-Exit等。因此应当尽可能批量处理数据,同时减少事件的通知。
标准:virtqueue
所有Virtio设备使用同一套称为virtqueue的机制,其内部实现是两个标准环形缓冲区和一个描述符列表,如图6所示。Virtqueue是一个分散-聚集缓冲区队列,主要有以下三种操作方式:
add_buf 在virtqueue中添加请求/响应;
get_buf 在virtqueue中获得响应/请求;
kick 通知对方virtqueue已经被更新;
virtqueue由Virtio前端驱动程序在guest物理内存中创建。Virtio后端驱动程序只需要调用Virtio API解析virtqueue的结构即可获得请求或响应。如何构建virtqueue则取决于guest操作系统。在Linux中实现Virtio时,virtqueue被实现为一个称为vring的环形缓冲结构。
在ACRN的Virtio前端驱动程序开发过程中,virtqueue API可被直接利用,从而用户无需关心virtqueue的具体内部细节。关于virtqueue实现的更多细节,请参考您所使用的guest操作系统。
所有Virtio设备使用同一套称为virtqueue的机制,其内部实现是两个标准环形缓冲区和一个描述符列表,如图6所示。Virtqueue是一个分散-聚集缓冲区队列,主要有以下三种操作方式:
add_buf 在virtqueue中添加请求/响应;
get_buf 在virtqueue中获得响应/请求;
kick 通知对方virtqueue已经被更新;
virtqueue由Virtio前端驱动程序在guest物理内存中创建。Virtio后端驱动程序只需要调用Virtio API解析virtqueue的结构即可获得请求或响应。如何构建virtqueue则取决于guest操作系统。在Linux中实现Virtio时,virtqueue被实现为一个称为vring的环形缓冲结构。
在ACRN的Virtio前端驱动程序开发过程中,virtqueue API可被直接利用,从而用户无需关心virtqueue的具体内部细节。关于virtqueue实现的更多细节,请参考您所使用的guest操作系统。
可扩展:特征bit
每个Virtio设备和其Virtio前端驱动程序之间都存在一个简单可扩展的特征协商(feature negotiation)机制。每个Virtio设备都可以声明其设备特定的功能,而相应地Virtio前端驱动程序可以表示自己能够理解哪些硬件特征。这种特征协商的机制能够保证驱动程序向前和向后兼容。
每个Virtio设备和其Virtio前端驱动程序之间都存在一个简单可扩展的特征协商(feature negotiation)机制。每个Virtio设备都可以声明其设备特定的功能,而相应地Virtio前端驱动程序可以表示自己能够理解哪些硬件特征。这种特征协商的机制能够保证驱动程序向前和向后兼容。
在ACRN参考实现中,Virtio前端驱动程序存在于guest操作系统的内核态空间,而Virtio后端驱动程序则存在两种可能:用户态和内核态。图9显示了ACRN中用户态的Virtio后端驱动程序架构。
Figure 9 Virtio框架 – 用户态程序
在ACRN virtio后端驱动框架中,该实现兼容virtio标准规范0.9和1.0版本。VBS-U与设备模型静态链接,并通过PCIe/PCI虚拟设备接口(PIO/MMIO或MSI/MSIx)与设备模型通信。VBS-U通过用户态virtqueue API来访问Virtio前端驱动程序在共享内存中放置的数据。SOS访问UOS物理内存则是基于ACRN hypervisor的帮助。
Figure 10 Virtio框架- 内核态程序
从性能角度出发,为了支持一些性能要求较高的设备,数据平面(data plane)的处理可以从用户态挪到内核态,从而避免Virtio后端驱动在用户态和内核态切换时产生额外的数据搬运;而控制平面(control plane)的处理,仍然保留在用户空间,即VBS-U中。VBS-U需要选择在正确的时间初始化VBS-K,例如,Virtio前端驱动设置VIRTIO_CONFIG_S_DRIVER_OK时就是一个不错的时机。运行在内核态的Virtio后端驱动可以使用VBS-K virtqueue API前端驱动共享的数据。考虑到易用性,VBS-K virtqueue API与VBS-U virqueue API设计得极为相似。此外,VBS-K依赖于VHM,即VHM负责分发IOREQ给VBS-K模块。每个VBS-K需要处理一类或者多类IOREQ请求,具体多少取决于特定的VBS-K需要监听多少段连续的寄存器空间。最后,VBS-K借助于VHM的API来通过中断的方式通知Virtio前端驱动程序。
看到这里,开发者们是不是有兴趣亲自动手实践了,如果您在项目设计中遇到关于ACRN的技术问题,欢迎访问ACRN社区进行讨论,社区地址:
https://projectacrn.github.io/latest/index.html。