分类:知识大全时间:2023-03-06 09:48作者:未知编辑:猜谜语
I/O虚拟化是SmartNIC/DPU/IPU的核心部分。AWS NITRO从I/O硬件虚拟化开始,逐渐开始了DPU这种新处理器类型的革新。Virtio接口已经是云计算虚拟化事实上的标准化接口。Virtio成为了整个问题的焦点:无论是SPDK/vhost还是vDPA加速,都是围绕Virtio接口展开的。
1 I/O设备虚拟化:从软件模仿到SR-IOV
I/O虚拟化是计算机虚拟化中最复杂的部分,因为它涉及CPU、操作系统、Hypervisor和I/O设备的协作。I/O虚拟化也经历了从软件模仿虚拟化、准虚拟化到完全硬件虚拟化的转变。
A.I/O软件模仿虚拟化和准虚拟化。
I/O设备虚拟化场景不仅要关注I/O设备模仿,还要关注vCPU与虚拟I/O设备的交互。很多条件交织在一起,使得整个问题非常复杂。I/O虚拟化的性能成本主要体现在三个方面:驱动访问设备寄存器的成本;通过中断和DMA访问驱动设备的成本;器件模仿本身的成本。因此,I/O虚拟化性能优化主要通过五个角度进行:
降低I/O访问寄存器的成本:一方面,部分I/O访问改为MMIO访问,无需陷入Hypervisor;另一方面,这是优化VM-exit/VM-entry交换的成本。
减少I/O访问次数:比如简化通知机制,简化虚拟化设备的功能。
优化中断:主要像APIC中断的硬件虚拟化或者无中断的轮询驱动。
降低DMA访问的成本:通过IOMMU实现直通模式等等。
降低器件仿真成本:硬件器件主要通过硬件SR-IOV机制实现。
如图1(a)所示,虚拟机中的设备通常由虚拟机治理程序模仿。虚拟设备的功能可以少于或多于物理设备,甚至可以模仿一些不存在的特性,可以模仿不存在的硬件设备。通过I/O软件仿真的方式,我们称之为I/O设备软件仿真虚拟化。在I/O软件模仿虚拟化的解决方案中,客户端VM需要使用底层硬件资源,需要Hypervisor拦截每个哀求指令,然后模仿这些指令的行为。我们都知道Hypervisor拦截指令的动作是从VM-exit,处理模仿,再到VM-entry的过程。这个过程代价非常大,每条指令都必须这样,必然带来巨大的性能开销。
如图1(b)所示,Virtio提供了一种类虚拟化的方法,客户端完成设备的前端驱动,Hypervisor配合客户端完成相应的后端驱动,这样通过两者之间的交互机制就可以实现一个高效的虚拟化过程。
Virtio框架如图2所示,使用VirtQueue实现其I/O机制,每个Virtqueue都是一个承载大量数据的队列。VRing是Virtqueue的详细实现,会有相应的描述符表来描述。Virtio是一个通用的驱动程序和设备接口框架。基于Virtio,已经实现了许多不同类型的模仿设备和设备驱动程序,如Virtio-net、Virtio-blk、Virtio-scsi。
Virtio类虚拟化相对于传统I/O设备软件模仿的性能优势在于,很多控制和状态信息不需要寄存器读写,而是写入Virtqueue的相关数据结构中,使驱动程序和设备进行交互。并且在数据交互中,只有当某一批数据变更需要对方处理时,才会通知对方。驱动器通过写入Kick寄存器来通知器件,器件通过中断来通知驱动器。
B.I/O完全硬件虚拟化
评价I/O虚拟化技术的两个指标的性能和通用性。性能,当然I/O性能越接近非虚拟化环境越好;通用性意味着I/O虚拟化对客户操作系统尽可能透明。实现高性能最直接的方法就是让客户端直接使用真实的硬件设备。为了具有通用性,有必要找到使客户机的驱动程序运行的方法
客户端直接操作设备有两个问题:一是如何让客户端直接访问设备的真实I/O地址空间(包括I/O和MMIO);第二,如何让设备的DMA直接访问客户端的内存空间。内存硬件虚拟化EPT技术可以解决第一个问题。而VT-d技术用于解决第二个问题。VT-d技术主要介绍IOMMU IOTLB,负责提供设备的重映射和直接分配。来自设备端的DMA访问会进入地址重映射进行地址转换,这样设备就可以访问对应客户端的特定内存区域。
虽然VT-d技术可以直接将物理I/O设备传输到虚拟机,但是一个计算机系统受到接口的限制,能够连接的物理设备终究是有限的。因此,PCIe SR-IOV技术应运而生。借助PCIe SR-IOV技术,一个物理I/O设备可以虚拟化多个虚拟设备,并将它们分配给虚拟机。
如图1(c)所示,SR-IOV引入了两种PCIe功能类型:
PFs(物理功能):所有PCIe设备,包括治理SR-IOV的功能。
VFs(虚拟功能):一种轻量级PCIe设备,只能执行必要的配置和数据传输。
Hypervisor将VF分配给虚拟机,并通过IOMMU等硬件辅助技术提供的DMA数据映射,在虚拟机和硬件设备之间直接传输数据。
C.I/O虚拟化摘要
I/O虚拟化技术从兼容性、性能、成本、扩展性四个方面进行总结。详见表1:
表1不同I/O虚拟化方法的比较
I/O虚拟化模式VM兼容性性能成本扩展性设备接口软件模仿重用现有驱动程序频繁上下文切换无额外硬件成本受设备模仿类性能成本约束虚拟化前端和后端需要加载特定驱动程序。基于共享队列的机制在不增加额外硬件成本的情况下减少了前端交互,直接分配VT-d复用设备驱动直接访问物理设备。为了降低虚拟化开销,您需要购买更多的硬件和硬件设备的排他性。由于主板扩展槽的限制,直接分配SR-IOV需要加载VF驱动直接访问物理设备。要降低虚拟化开销,需要购买更多的硬件和硬件设备来支持多个虚拟设备,具有良好的可扩展性。
2通用接口虚拟化
Virtio旨在提供一套高效且维护良好的通用Linux驱动程序,实现不同Hypervisor实现的虚拟机应用程序和仿真设备之间的标准化接口。Virtio作为一种虚拟I/O设备接口,广泛应用于云计算虚拟化场景。在某种程度上,Virtio已经成为I/O设备事实上的接口标准。
当我在前一节介绍I/O虚拟化时,Virtio是作为一种I/O类虚拟化技术介绍的。本节将省略与虚拟化相关的内容,具体阐述作为标准接口的Virtio。
2.1虚拟寄存器
有三种类型的虚拟寄存器:设备状态字、功能特征位和PCIe配置空间。
A.设备状态字
如表2所示,器件状态字段标识初始化序列步骤的完成。
表2设备状态字描述
位位置状态字值定义描述01确认意味着操作系统已找到设备并将其识别为有效的虚拟设备12驱动意味着操作系统已找到设备并将其识别为有效的虚拟设备24驱动程序_正常意味着驱动程序已安装并预备好驱动设备38功能_正常意味着驱动程序已确认其理解的所有功能。并且功能协商完成416。保留位532和保留位664 Device _ Needs _ Reset表示设备碰到了不可恢复的错误。7128FAILED表示操作系统有问题,或者驱动程序和设备功能不匹配,或者在设备操作过程中出现致命错误。
根据设备状态字,Virtio协议定义并限制驱动程序必须按以下顺序初始化设备:
(1)重置设备。
(2)设置确认状态位,表示操作系统已经发现了该设备。
(3)设置驱动程序状态位表示操作系统知道如何驱动该设备。
(4)读取设备的功能位,并将操作系统和驱动程序能够理解的功能位子集写入设备。
(5)设置F
(6)重新读取设备状态。假如FEATURES_OK的读取结果仍旧是1,说明设备已经接受了驱动程序的功能子集;否则,假如为0,则表示设备不支持驱动程序的功能子集,设备不可用。
(7)执行设备特定的设置,包括发现设备的虚拟队列,读取和可能写入设备的虚拟配置空间,以及填充虚拟队列。
(8)将DRIVER_OK状态位设置为1。此时,设备初始化完成,设备处于活动状态。
(9)假如在上述任何步骤中出现不可恢复的错误,驱动程序将把失败状态位设置为1。
B.功能特征位
每个虚拟设备提供与其支持的所有功能相对应的功能特征位。在设备初始化期间,驱动程序将读取该信息,并通知设备它接受的子集。
这样就可以实现向前和向后兼容:假如设备增加了新的功能位,老的驱动就不会把功能位写回设备(意味着这个功能不会开启)。同样,假如驱动程序增加了一个新的功能,但是设备没有提供这个功能,同样的功能也不会写回设备(意味着这个功能不会开启)。
Virtio1.1协议中的功能位分配如下:
位023:特定设备类型的功能位;
2437位:预留功能位,用于扩展队列和功能协商机制;
38位以上:保留功能位以备将来扩展。
C.构形空间
与标准的PCI配置空间相比,Virtio over PCI使用的配置空间在其供给商ID和设备ID方面比较特别。Virtio的厂商ID为0x1AF4,其设备ID号为0x1040-0x107F。
为了与PCI功能格式兼容,由Virtio定义的Virtio _ PCI _ cap的格式如表3所示。
表3 virt io的PCI能力结构
字节3字节2字节1字节00x CFG _ type cap _ lencap _ vndr cap _ vndr0x 4 padding bar0x 8 offset0x clength
其中cfg_type标识virtio_pci_cap类型,有五种类型,代表五组映射在BAR空间的寄存器。virtio_pci_cap的类型如表4所示。
表4虚拟PCI功能类型
类型名称ID描述VIRTIO_PCI_CAP_COMMON_CFG1一般配置VIRTIO_PCI_CAP_NOTIFY_CFG2通知VIRTIO_PCI_CAP_ISR_CFG3ISR状态VIRTIO_PCI_CAP_DEVICE_CFG4设备特定配置virtio _ PCI _ cap _ cfg5pci配置访问。
2.2虚拟队列交互队列
Virtio 1.1引入了Packed Virtqueue的概念,Virtio 1.0对应的Virtqueue称为Split Virtqueue。
如图3所示,这是Virtio1.0的分割Virtqueue结构。Virtqueue由三部分组成:
描述符表
可用描述符环
用过的描述符环
Virtio 1.0的Split Virtqueue有一些缺点:
假如虚拟场景软件模仿Virtio设备,由于数据结构分散,缓存利用率低,每次哀求都会有很多缓存未命中;
假如在硬件中实现,每个描述符需要多次设备DMA访问。
如图4所示,Virtio 1.1引入了打包虚拟队列的概念。整个描述符只有一个数据结构。这样,假如软件实现Virtio设备模仿,可以提高描述符交互的缓存命中率。假如用硬件实现,可以减少设备DMA的访问次数。
2.3虚拟互动
驱动程序和设备之间的交互符合生产者-消费者模型的数据和通知的交互行为。驱动程序预备共享队列的队列项,并通过写寄存器通知设备。当设备收到驱动发送的通知时,会处理队列项和相应的数据处理工作,然后更新队列状态并通知(设备通知驱动被中断驱动)。当驱动程序接收到中断通知时,它释放已用队列项并更新队列状态。
驱动程序和设备之间的典型交互流程如图5所示。虚拟场景的驱动程序与设备交互。驱动给设备的通知叫Kick,设备给驱动的通知叫Interrupt。踢和中断操作是虚拟接口的一部分。在虚拟化场景中,Kick和Interrupt需要非常高的CPU切换成本。驱动希望在Kick之前生成尽可能多的缓冲项进行处理(一个缓冲项对应一个描述符和描述符指向的数据块);类似地,设备希望在发送中断之前处理尽可能多的缓冲项。通过处理尽可能多的缓冲区,稀释了通知的成本。
这种策略是一种理想的状态,因为大部分时候驾驶员并不知道下一套缓冲物品什么时候会带来,所以每套缓冲物品预备好之后他都得有Kick装置。同样,设备在处理完相应的缓冲项后,尽快向驱动程序发送中断,以达到最小的延迟。
如图6所示,在设备模仿的虚拟化场景中,驱动程序可以暂时禁用中断,设备也可以暂时禁用Kick。通过这种机制,可以在不影响性能和延迟的情况下最小化通知的成本。Virtio 1.1支持两种通知抑制机制,因此有三种模式:
启用通知模式:完全不禁止,启用通知;
禁用通知模式:如图6所示,可以完全禁止对方给自己发送通知;
启用特定描述符通知模式:通知对方一个特定的描述符,当对方顺序处理这个描述符时产生通知。
2.4总结
如图7所示,Virtio基于分层设计思想定义了一个三层Virtio设备架构:
最低的总线接口。PCI是Virtio场景中最常用的总线,但是Virtio协议不仅支持PCI,还支持MMio和通道IO。
通用虚拟交互界面。包括虚拟队列、功能特征位、配置空间等。Virtio交互接口是Virtio的核心功能,通过Virtio交互接口实现不同类型设备的标准化。
上层特定设备接口。在Virtio协议中,定义了网络、块、控制台、SCSI和GPU等不同类型的设备。
Virtio的优势如下:
Virtio实现了尽可能多的设计共享。这样在开发过程中可以重用大量的软硬件资源,达到快速开发的目的。
Virtio标准化了接口。标准化体现在两个方面:
(1)一个是通用的Virtio交互接口,统一了不同设备类型的软硬件之间的交互;
(2)基于Virtio的Virtio-net和Virtio-block广泛应用于云计算虚拟化场景,Virtio已经成为事实上的标准I/O接口。
Virtio的缺点是Virtio实现了接口的标准化,忽略了不同设备类型数据传输的特点。所以在一些数据传输量大的场景下,效率相对较低。假如是在像HPC这样对性能和延迟非常敏感的场景中,Virtio并不是一个好的选择。
3虚拟化卸载
虚拟化卸载是指卸载计算机虚拟化中消耗CPU资源较多的接口设备模仿、热迁移、虚拟化治理等任务。
A.接口设备的卸载
前面我们介绍了网络、远程存储等IO任务的卸载,而虚拟化卸载主要是指网络、存储等与IO相关的接口设备的卸载。卸载IO接口设备本身也是IO硬件虚拟化的过程。例如,我们可以通过VT-d技术从VM访问硬件设备,这在某种程度上也可以认为是将运行在Hypervisor中的模仿设备“卸载”到硬件上。所以IO接口设备的卸载本质上和IO设备的硬件虚拟化是一回事。
如图8所示,为了规范设备接口,加快io处理性能,潜在地充分利用现有的虚拟化生态(比如更好地支持设备热迁移),阿里云在神龙芯片中实现了硬件的Virtio接口设备,通过支持Virtio-net网络驱动和Virtio-blk存储驱动,实现了类Virtio虚拟化IO设备的硬件“卸载”。
AWS的NITRO系统支持网络、本地存储和远程存储。NITRO实现了网络接口设备ENA/EFA(AWS自定义接口)和存储接口设备NVMe(远程存储EBS使用NVMe接口,本地存储也是NVMe接口)的硬件“卸载”。
B.卸载后接口设备的迁移
当设备被“卸载”到硬件时,VM可以直接访问硬件设备,这使得VM的设备热迁移非常具有挑战性。VDPA(vhost数据路径加速,其中vhost通过Virtio后端设备模仿的轮询方式实现)实现了一种折中的解决方案。如图9所示,VDPA将虚拟化分为控制平面和数据平面:
控制表面。vDPA控制平面仍用于设备和虚拟机之间的配置更改和功能协商,以及建立和终止数据平面。
数据层。vDPA数据平面包括共享队列和相应的通知机制,用于在设备和虚拟机之间传输实际数据。
使用vDPA的一个重要原因是,在热迁移期间,可以方便地将Virtio数据平面的处理切换回传统的Virtio/Vhost后端设备模仿。这样,可以充分利用现有的基于KVM/Qemu的虚拟设备迁移解决方案来完成设备迁移。
C.卸载虚拟化治理
从软件虚拟化到硬件虚拟化的演进,本身可以看作是一个硬件加速和硬件卸载的过程。我们逐渐剥离了Hypervisor的功能,比如通过VT-x技术“卸载”Hypervisor的CPU/内存的软件模仿,通过VT-d、vDPA等技术“卸载”设备软件模仿。这些剥离使得Hypervisor越来越轻,整个系统的虚拟化开销越来越少。此外,我们可以将虚拟化治理(如Linux平台的主流治理程序Libvirt)卸载到硬件中的嵌入式软件上运行。
如图10所示,我们通过桥接实现了嵌入式软件在主机软硬件中的通信机制。将虚拟化治理等软件任务从主机卸载到嵌入式系统(仍有少部分任务无法卸载,如虚拟机资源分配、vCPU调度等)。这样就可以将几乎100%的主机资源提供应用户,让用户的虚拟机获得近乎物理机的性能。
通过虚拟化卸载到硬件中的嵌入式CPU软件,我们可以将业务和治理进行物理分离,整个业务主机与云计算治理网络安全隔离,因此我们只能通过特定的接口访问Lite Hypervisor,我们无法访问主机的任何资源。这样,即使存在潜在的操作错误,也不会影响业务主机。