7.1 虚拟机直接IO原理与架构

引:https://blog.csdn.net/wanthelping/article/details/47069469
7.1.1 虚拟机直接虚拟化原理与难点

第5与第6章分别讲解了qemu/kvm的硬件辅助IO模拟虚拟化与virtio半虚拟化.

模拟I/O设备方式的优点是对硬件平台依赖性较低、可以方便模拟一些流行的和较老久的设备、不需要宿主机和客户机的额外支持,故兼容性高;而其缺点是I/O路径较长、VM-Exit次数很多,故性能较差。一般适用于对I/O性能要求不高的场景。 Virtio半虚拟化设备方式的优点是实现了VIRTIO API,减少了VM-Exit次数,提高了客户机I/O执行效率,比普通模拟I/O的效率高很多;而其缺点是需要客户机中virtio相关驱动的支持(较老的系统默认没有自带这些驱动,Windows系统中需要额外安装virtio驱动),故兼容性较差,而且I/O频繁时的CPU使用率较高。 而本节方式叫做PCI设备直接分配(Device Assignment,或者PCI pass-through),它允许将宿主机中的物理PCI(或PCI-E)设备直接分配给客户机完全使用.

其工作架构如下图所示:

左侧为直接IO, 右侧为模拟IO虚拟化.

VM虚拟机支持将宿主机中的PCI、PCI-E设备附加到虚拟化的客户机中,从而让客户机以独占方式访问这个PCI(或PCI-E)设备.在客户机看来,设备是物理上连接在其PCI(或PCI-E)总线上的,客户机对该设备的I/O交互操作和实际的物理设备操作完全一样,这不需要(或者很少需要)VMM的参与.

但我们知道,硬件虚拟化需要考虑dma传输与中断的注入. 由于guest os的gpa不是直接物理内存, 设备不能直接使用gpa进行dma传输. 其二, 设备产生的中断也不能直接传递给guest os. 为此intel定义了I/O虚拟化技术规范为“Intel® Virtualization Technology forDirected I/O”(VT-d), 来解决这些问题.

设备直接分配让客户机完全占有PCI设备,在执行I/O操作时大量地减少了(甚至避免)了VM-Exit陷入到Hypervisor中,极大地提高了I/O性能,可以达到和Native系统中几乎一样的性能。尽管Virtio的性能也不错,但VT-d克服了其兼容性不够好和CPU使用率较高的问题。不过,VT-d也有自己的缺点,一台服务器主板上的空间比较有限,允许添加的PCI和PCI-E设备是有限的,如果一个宿主机上有较多数量的客户机,则很难给每个客户机都独立分配VT-d的设备。另外,大量使用VT-d独立分配设备给客户机,让硬件设备数量增加,故增加了硬件投资成本。为了避免这两个缺点,可以考有两种解决方案: (1)在一个物理宿主机上,仅给少数的对I/O(如网络)性能要求较高的客户机使用VT-d直接分配设备(如网卡),而其余的客户机使用硬件辅助模拟(emulated)或使用Virtio以

达到多个客户机共享同一个设备的目的。二是,对于网络I/O的解决方法,可以选择SR-IOV让一个网卡产生多个独立的虚拟网卡,将每个虚拟网卡分别分配给一个客户机使用. 本文将只讨论第一种方案.

7.1.2 Intel VT-D概述

Intel VT-d技术是一种基于North Bridge北桥芯片(或者按照较新的说法:MCH)的硬件辅助虚拟化技术,通过在北桥中内置提供DMA虚拟化和IRQ虚拟化硬件,实现了新型的I/O虚拟化方式,Intel VT-d能够在虚拟环境中大大地提升 I/O 的可靠性、灵活性与性能。

传统的IOMMUs(I/O memorymanagement units,I/O内存管理单元)提供了一种集中的方式管理所有的DMA——除了传统的内部DMA,还包括如AGPGART、TPT、RDMA over TCP/IP等这些特别的DMA,它通过在内存地址范围来区别设备,因此容易实现,却不容易实现DMA隔离,因此VT-d通过更新设计的IOMMU架构,实现了多个DMA保护区域的存在,最终实现了DMA虚拟化。这个技术也叫做DMA Remapping。

I/O设备会产生非常多的中断请求,I/O虚拟化必须正确地分离这些请求,并路由到不同的虚拟机上。传统设备的中断请求可以具有两种方式:一种将通过I/O中断控制器路由,一种是通过DMA写请求直接发送出去的MSI(message signaled interrupts,消息中断),由于需要在DMA请求内嵌入目标内存地址,因此这个架构须要完全访问所有的内存地址,并不能实现中断隔离。 VT-d实现的中断重映射(interrupt-remapping)架构通过重新定义MSI的格式来解决这个问题,新的MSI仍然是一个DMA写请求的形式,不过并不嵌入目标内存地址,取而代之的是一个消息ID,通过维护一个表结构,硬件可以通过不同的消息ID辨认不同的虚拟机区域。VT-d实现的中断重映射可以支持所有的I/O源,包括IOAPICs,以及所有的中断类型,如通常的MSI以及扩展的MSI-X。

(1) 设备映射数据结构

a. 源标识。 出现在地址硬件地址转换上的DMA和中断都需要标示一个请求的发起端。 对pci设备而言用(总线号,设备号,功能好)标示。

b. 根条目: rootentry作为设备直接分配的顶层分配结构,它把特定的pci总线映射到对应的guest os.它包含当前标志(用来表明根条目是否已经存在和初始化) 和上下文条目

每个根条目对应一条pci总线,所有根条目组成一张根条目表;每个条目表最多256个根条目。下图表明了根条目表与上下文条目表的对应关系:

上下文条目(context-entry)将pci总线上的某个设备映射到某个guest os.它为分配该设备的guest os映射到地址转换结构。它包含如下内容:

a. 域标识: 它标识出哪些源标示符的设备被分配给guest os.

b. 转换类型: 用来转换一个DMAoperation

c. 地址宽度: 被分配的guest的地址宽度

(2)IO的映射表

它与MMU表相似,下图是三级io映射表

(3) IOTLB

与TLB相似, IOTLB用来缓存DMA地址转换中的映射条目。它也支持invalidate,

a) 全局invalidate,清空整个iotlb

b) guest选择invalidate, 这选择某个guest的清空

c) guest页面选择invalidate: 这清空某个guest的某些条目

7.1.3 直接IO的使用

要在LInux kvm/qeum使用直接IO 需要满足以下条件:

(1) CPU 支持 VT-D

(2) Host Linux OS enable IOMMU, DMAR

(3) Host Linux Enable PCI_STUB driver.

使用方法:

(1) 用pci-stub在linux host os 上屏蔽相关pci 设备

echo -n “vendorid:deviceid” >/sys/bus/pci/drivers/pci-stub/new_id

echo “xxxx:yy:zz.v” > /sys/bus/pci/devices/“xxxx:yy:zz.v”/driver/unbind

echo “xxxx:yy:zz.v” >/sys/bus/pci/devices/pci-stub/binds

添加如下参数启动kvm

pci-assign,?kvm-pci-assign.host=“bus.dev.func”

Pci-stub driver实际上是一个空实现的pcidriver,VM host使用它就不会主动访问该设备了,

其代码位于:drivers\pci\pci-stub.c.

KVM/QEMU依赖于IOMMU,下一节将从分析qemu pci-assign模块开始分析.


本文来自 wanthelping 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/wanthelping/article/details/47069469?utm_source=copy

猜你喜欢

转载自blog.csdn.net/weixin_42681961/article/details/82827509
7.1
今日推荐