一、背景
SR-IOV(Single Root I/O Virtualization)是由PCI-SIG組織定義的PCIe規范的擴展規范《Single Root I/O Virtualization and Sharing Specification》,目的是通過提供一種標準規范,為VM(虛擬機)提供獨立的內存空間、中斷、DMA數據流,當前最新版本為1.1。
圖1.1
IO虛擬化有軟件模擬、基於virtio的半虛擬化和設備直通三種方式,見圖1.1,其中設備直通實現瞭數據面加速,允許物理PCIe設備可以直接訪問虛擬機的GuestOS中運行相應驅動分配的物理地址(GPA)。
SR-IOV的出現,支持瞭單個物理PCIe設備虛擬出多個虛擬PCIe設備,然後將虛擬PCIe設備直通到各虛擬機,以實現單個物理PCIe設備支撐多虛擬機的應用場景,如圖1.2。
圖1.2
二、SR-IOV原理
2.1 硬件實現
2.1.1 SR-IOV基本結構
SR-IOV是在PCIe規范的基礎上實現的,SR-IOV協議引入瞭兩種類型功能的概念:物理功能 (Physical Function, PF)和虛擬功能 (Virtual Function, VF),基本結構見圖2.1.1。
圖2.1.1
PF用於支持 SR-IOV 功能的 PCI 功能,如 SR-IOV 規范中定義,PF 包含 SR-IOV 功能配置結構體,用於管理 SR-IOV 功能。PF 是全功能的 PCIe 功能,可以像其他任何 PCIe 設備一樣進行發現、管理和處理。PF 擁有完全配置資源,可以用於配置或控制 PCIe 設備。
VF是與PF關聯的一種功能,是一種輕量級 PCIe 功能,可以與物理功能以及與同一物理功能關聯的其他 VF 共享一個或多個物理資源。VF 僅允許擁有用於其自身行為的配置資源。
2.1.2 VF的BAR空間資源
VF的BAR空間是PF的BAR空間資源中規劃的一部分,VF不支持IO空間,所以VF的BAR空間也需要映射到系統內存,VF的BAR空間的物理資源排佈如圖2.1.2:
圖2.1.2
2.1.3 PF的SR-IOV Extended Capabilities 配置
PF的PCIe擴展配置空間 SR-IOV Extended Capability支持對SR-IOV功能進行配置,如圖2.1.3:
圖2.1.3
其中SR-IOV Control 字段的bit0位是SR-IOV的使能位,默認為0,表示關閉,如果需要開啟SR-IOV功能,需要配置為1。
TotalVFs字段表示PCIe Device支持VF的數量。
NumVFs字段表示開啟VF的數量,此值不應超過PCIe Device支持的VF的數量TotalVFs的值。
First VF Offset字段表示第一個各VF相對PF的Routing ID(即Bus number、Device number、Function number)的偏移量。
VF Stride字段表示相鄰兩個VF的Routing ID的偏移量。
其他字段含義詳見《Single Root I/O Virtualization and Sharing Specification Revision 1.1》。
2.2 軟件支持
Linux系統下,基於SR-IOV有三種應用場景:HostOS使用PF、HostOS使用VF、將VF直通到VM(虛擬機),見圖2.2.1:
圖2.2.1
Linux系統中PCI驅動框架drivers/pci/iov.c提供瞭一系列對SR-IOV Extended Capability的配置接口函數,PCIe Device需要有相應的PF驅動和VF驅動,PF驅動支持配置SR-IOV,VF驅動需要實現相應的PCIe Device的業務功能(例如NIC或GPU),VFIO中的vfio-pic是一個簡易符合VFIO框架PCIe驅動。
三、基於SR-IOV的IO虛擬化
3.1 基於QEMU/KVM的PCIe設備直通框架
在QEMU/KVM的虛擬化架構下,PCIe設備直通的軟硬件系統架構由下往上有如下幾部分(見圖3.1):
l PCIe Device(支持SR-IOV功能)
l IOMMU
l VFIO
l Hypervisor(QEMU/KVM)
l VF Driver(運行在GuestOS中)
圖3.1
3.1.1 IOMMU
IOMMU(I/O Memory Management Unit)是一個內存管理單元,主要針對外設訪問系統內存市進行內存管理,像intel VT-d、AMD的IOMMU及ARM的SMMU都具有相同功能。IOMMU支持PCIe Device虛擬化的兩個基礎功能:地址重映射和中斷重映射。
3.1.1.1 DMA物理地址重映射
(DMA Remapping )
1)地址空間隔離
在沒有iommu的時候,用戶態驅動可以通過設備dma可以訪問到機器的全部的地址空間,如何保護機器物理內存區對於用戶態驅動框架設計帶來挑戰。引入iommu以後,iommu通過控制每個設備dma地址到實際物理地址的映射轉換,可以實現地址空間上的隔離,使設備隻能訪問規定的內存區域,見圖3.1.1.1.1。
圖3.1.1.1.1
2)GPA(虛擬機物理地址) –> HPA(宿主機物理地址)
物理PCI設備通過直通的方式進入到虛擬機的客戶機時,客戶機設備驅動使用透傳設備的DMA訪問虛擬機內存物理地址時,IOMMU會進行 GPA–>HPA的轉換,詳細轉換細節在下一章節分析。
3.1.1.2 中斷重映射
以Intel VT-d為例,提出瞭兩個機制支持中斷重映射:
引入兩種中斷請求格式
兼容模式和重映射模式,Bit4位為0來表征為不可重映射中斷,Bit4位為
1來表征為可重映射中斷,見圖3.1.1.2.1和圖3.1.1.2.2。
圖3.1.1.2.1
圖3.1.1.2.2
引入Interrupt Remapping Table Entry (IRTE)
Interrupt Remapping Table Entry是一個二級表,需要先通過Interrupt Remapping Table Address Register來找到Interrupt Remapping Table Entry所在的地址,Interrupt Remapping Table Entry的格式如圖3.1.1.2.3:
圖3.1.1.2.3
IOMMU中斷重映射的實質是將來自PCIe設備的中斷(包括來自IOAPIC和PCIe設備的MSI/MSI-X等)攔截下來判斷是否為重映射中斷,如果是重映射中斷會通過查詢中斷映射表(Interrupt Remapping Table Entry)找到真正的中斷路由信息然後發送給物理CPU。
3.1.2 VFIO
VFIO(Virtual Function I/O)是基於IOMMU為HostOS的用戶空間暴露PCIe設備的配置空間和DMA。VFIO的組成主要有以下及部分,見圖3.1.2.1:
圖3.1.2.1
l VFIO Interface:
VFIO通過設備文件向用戶空間提供統一訪問接口:
• Container文件描述符:打開/dev/vfio字符設備可得
• IOMMU group文件描述符:打開/dev/vfio/N文件可得
• Device文件描述符:向IOMMU group文件描述符發起相關ioctl可得
l vfio_iommu_type1_driver:
為VFIO提供瞭IOMMU重映射驅動,向用戶空間暴露DMA操作。
l vfio-pci:
vfio支持pci設備直通時以vfio-pci作為pci設備驅動掛載到pci總線, 將pci設備io配置空間、中斷暴露到用戶空間。
3.1.3 QEMU/KVM PCI設備直通
QEMU/KVM 的PCI設備直通QEMU的核心工作主要有兩部分:
1) 讀取PCIe設備信息
通過VFIO接口讀取PCIe設備的配置空間和DMA信息,
2) 為虛擬機創建虛擬PCIe設備
為虛擬機創建虛擬PCIe設備,虛擬PCIe設備的寄存器規劃和DMA信息是物理PCIe設備在虛擬機中的映射。
QEMU中PCI設備直通時vfio-pci註冊流程見圖3.1.3.1:
圖3.1.3.1
QEMU中PCI設備直通時vfio-pci初始化流程見圖3.1.3.2:
圖3.1.3.2
3.2 PCI設備直通數據面加速
PCI設備直通時,GuestOS中的設備驅動操作虛擬PCI設備的DMA時,QEMU會將上述操作通過VFIO接口下發給物理PCI設備的DMA,物理設備DMA收到GuestOS中的物理地址GPA,通過IOMMU的映射,找到Host主機物理內存的物理地址HPA,達到物理PCI設備直接訪問GuestOS中的GPA,從而達到數據數據面加速。
3.2.1 GPA->HPA的映射過程
對於直通的設備,QEMU創建虛擬機時需要兩方面的地址映射,見圖3.2.1.1:
1)VM在創建時GuestOS的內存需要QEMU調用KVM最終通過EPT和MMU建立GVA->GPA->HPA的映射;
2)QEMU進行VM的虛擬PCI設備初始化時,會將HVA和GPA下發給IOMMU,
讓IOMMU建立GPA到HPA的映射關系。
當GuestOS中直通設備的驅動分配內存並配置DMA時,QEMU通過VFIO接口將GPA下發到PCI Device的DMA,DMA讀取數據時經由IOMMU映射,找到相應的HPA。
圖3.2.1.1
轉自Linux閱碼場:深入理解SR-IOV和IO虛擬化