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等實現Pass Through模式。
減少設備模擬的代價:則主要是通過硬件SR-IOV機制實現硬件設備。
如圖1(a),虛擬機中看到的設備,一般是由Hypervisor模擬出來的。虛擬設備的功能,可以少于也可以多于物理的設備,甚至可以模擬出一些不存在的特性,模擬出不存在的硬件設備。通過I/O軟件模擬的方式,我們稱之為I/O設備軟件模擬虛擬化。在I/O軟件模擬虛擬化的解決方案中,客戶機VM要使用底層的硬件資源,需要Hypervisor來截獲每一條請求指令,然后模擬出這些指令的行為。我們都知道Hypervisor截獲指令的動作就是從VM-exit,處理完模擬然后再VM-entry的過程,這個過程的代價很高,每條指令都要如此,帶來的性能開銷必然是非常龐大的。
如圖1(b)所示,Virtio提供的類虛擬化方式,客戶機完成設備的前端驅動程序,Hypervisor配合客戶機完成相應的后端驅動程序,這樣兩者之間通過交互機制就可以實現高效的虛擬化過程。
Virtio框架如圖2所示,使用Virtqueue來實現其I/O機制,每個Virtqueue就是一個承載大量數據的Queue。VRing是Virtqueue的具體實現方式,針對VRing會有相應的描述符表格進行描述。Virtio是一個通用的驅動和設備接口框架,基于Virtio分別實現了Virtio-net、Virtio-blk、Virtio-scsi等很多不同類型的模擬設備及設備驅動。
Virtio類虛擬化比傳統的I/O設備軟件模擬的性能優勢體現在:很多控制和狀態信息不需要通過寄存器讀寫操作來交互的,而是通過寫入Virtqueue的相關數據結構來讓驅動(Driver)和設備(Device)雙方交互。并且在數據交互的時候,只需要在一定批量數據變化需要對方處理的時候才會通知對方,驅動通知設備是通過寫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(Physical Functions):包括管理SR-IOV功能在內的所有PCIe設備。
VFs(Virtual Functions):輕量級的PCIe設備,只能進行必要的配置和數據傳輸。
Hypervisor把VF分配給虛擬機,通過IOMMU等硬件輔助技術提供的DMA數據映射,直接在虛擬機和硬件設備之間傳輸數據。
c. I/O虛擬化總結
通過兼容性、性能、成本、擴展性四個方面對I/O虛擬化技術進行總結,詳見表1:
表1 不同I/O虛擬化方式對比
I/O虛擬化方式 | VM的兼容性 | 性能 | 成本 | 擴展性 |
設備接口軟件模擬 | 重用已有驅動 | 頻繁的上下文切換 | 沒有額外硬件成本 | 受設備模擬的性能代價約束 |
類虛擬化前后端 | 需要加載特定驅動 | 基于共享隊列的機制減少了前后端交互 | 沒有額外硬件成本 | 受設備后端的性能代價約束 |
直接分配VT-d | 重用設備驅動 | 直接訪問物理設備,減少虛擬化開銷 | 需要購買額外的較多的硬件 | 硬件設備獨占性,受主板擴展槽限制 |
直接分配SR-IOV | 需要加載VF驅動 | 直接訪問物理設備,減少虛擬化開銷 | 需要購買額外的較少的硬件 | 硬件設備支持多個虛擬設備,擴展性較好 |
2 通用接口Virtio
Virtio旨在提供一套高效的、良好維護的通用的Linux驅動,實現虛擬機應用和不同Hypervisor實現的模擬設備之間標準化的接口。Virtio作為類虛擬化的I/O設備接口,廣泛應用于云計算虛擬化場景,某種程度上,Virtio已經成為事實上的I/O設備的接口標準。
在上一節介紹I/O虛擬化時,Virtio作為I/O類虛擬化技術做過介紹。本節會略去虛擬化相關的內容,把Virtio作為一個標準的接口進行詳細的闡述。
2.1 Virtio寄存器
Virtio寄存器有三種類型:設備狀態字、功能特征位以及PCIe配置空間。
a. 設備狀態字
如表2所示,設備狀態字(Device Status Field)標識了初始化序列步驟的完成情況。
表2 設備狀態字描述
Bit位置 | 狀態字值 | 定義 | 描述 |
0 | 1 | ACKNOWLEDGE | 表示操作系統已找到該設備并將其識別為有效的Virtio設備 |
1 | 2 | DRIVER | 表示操作系統已找到該設備并將其識別為有效的Virtio設備 |
2 | 4 | DRIVER_OK | 表示已安裝驅動程序并準備驅動設備 |
3 | 8 | FEATURES_OK | 表示驅動程序已確認其理解的所有功能,并且功能協商已完成 |
4 | 16 | 保留位 | 保留位 |
5 | 32 | 保留位 | 保留位 |
6 | 64 | DEVICE_NEEDS_RESET | 表示設備遇到了無法恢復的錯誤。 |
7 | 128 | FAILED | 表示操作系統出現問題,或者驅動和設備功能不匹配,或者設備運行過程中出現致命錯誤等。 |
基于設備狀態字,Virtio協議定義并約束了驅動程序必須按照以下順序初始化設備:
(1)重置設備。
(2)設置ACKNOWLEDGE狀態位,表示OS已發現此設備。
(3)設置DRIVER狀態位,表示OS知道如何驅動此設備。
(4)讀取設備功能位,并將操作系統和驅動程序可以理解的功能位子集寫入設備。
(5)設置FEATURES_OK狀態位。
(6)重新讀取設備狀態,如果FEATURES_OK讀取結果依然為1,則表示設備接受了驅動的功能位子集;否則,如果為0,則表示該設備不支持驅動的功能子集,該設備不可用。
(7)執行設備特定的設置,包括發現設備的虛擬隊列、讀取和可能寫入設備的virtio配置空間以及填充虛擬隊列等。
(8)將DRIVER_OK狀態位設置為1。此時,設備初始化完成,設備處于活動狀態。
(9)如果上述這些步驟中的任何一個發生不可恢復的錯誤,驅動程序會將FAILED狀態位設置為1。
b. 功能特征位
每個Virtio設備均提供其支持的所有功能對應的功能特征位。在設備初始化期間,驅動程序將讀取此信息并告知設備它接受的子集。
通過這種方式可以實現向前和向后兼容:如果設備增加了新功能位,則較舊的驅動程序就不會將該功能位寫回到設備中(意味著此功能不會被開啟)。同樣,如果驅動程序增加了新的功能,而設備未提供此功能,則同樣此功能不會被寫回到設備(意味著此功能不會被開啟)。
Virtio1.1協議中的功能位分配如下:
比特位0 – 23:特定設備類型的功能位;
比特位24 – 37:保留用于擴展隊列和功能協商機制的功能位;
比特位38以上:保留功能位以供將來擴展。
c. 配置空間
Virtio over PCI使用的配置空間與標準的PCI配置空間相比,特殊的地方在于其Vendor ID和Device ID。Virtio的Vendor ID為0x1AF4,其Device ID編號從0x1040-0x107F。
為了跟PCI Capabilities格式兼容,Virtio定義的virtio_pci_cap格式如表3所示。
表3 Virtio的PCI capability結構
Byte 3 | Byte 2 | Byte 1 | Byte 0 | |
0x0 | cfg_type | cap_len | cap_vndr | cap_vndr |
0x4 | padding | bar | ||
0x8 | offset | |||
0xC | Length |
其中cfg_type標識virtio_pci_cap類型,共有五種,代表了映射在BAR空間的五組寄存器。virtio_pci_cap類型如表4所示。
表4 Virtio PCI capability類型
類型名稱 | ID | 描述 |
VIRTIO_PCI_CAP_COMMON_CFG | 1 | 通用配置 |
VIRTIO_PCI_CAP_NOTIFY_CFG | 2 | 通知 |
VIRTIO_PCI_CAP_ISR_CFG | 3 | ISR狀態 |
VIRTIO_PCI_CAP_DEVICE_CFG | 4 | 設備具體的配置 |
VIRTIO_PCI_CAP_PCI_CFG | 5 | PCI配置訪問 |
2.2 Virtqueue交互隊列
Virtio 1.1引入了Packed Virtqueue的概念,對應的Virtio 1.0的Virtqueue被稱為Split Virtqueue。
如圖3所示,為Virtio1.0的Split Virtqueue結構。Virtqueue由三部分組成:
描述符表
可用的描述符環
已使用的描述符環
Virtio 1.0的Split Virtqueue具有一些缺點:
如果是虛擬化場景軟件模擬Virtio設備的話,因為分散的數據結構,導致Cache利用率較低,每次請求都會有很多Cache不命中;
如果是硬件實現的話,每次描述符需要多次設備DMA訪問。
如圖4所示,Virtio 1.1引入了Packed Virtqueue的概念。整個描述符只有一個數據結構。這樣,如果軟件實現Virtio設備模擬的話,可以提升描述符交互的Cache命中率。如果硬件實現的,可以降低設備DMA的訪問次數。
2.3 Virtio交互
驅動和設備的交互,符合生產者消費者模型的數據及通知(Notification)的交互行為。驅動把共享隊列的隊列項準備好,通過寫寄存器的方式通知設備。設備收到驅動發送的通知則處理隊列項以及相應的數據搬運工作,結束后更新隊列狀態并通知(設備通知驅動是通過中斷)驅動。驅動接收到中斷通知時候,把已經使用的隊列項釋放,并更新隊列狀態。
一個典型的通用的驅動和設備的交互流程如圖5所示。Virtio場景的驅動和設備交互,驅動給設備的通知(Notification)稱為Kick,設備給驅動的通知稱為Interrupt(中斷)。Kick和Interrupt操作是Virtio接口的一部分,在虛擬化場景,Kick和Interrupt需要非常大的CPU切換代價。驅動希望在Kick之前產生盡可能多的待處理緩沖項(一個緩沖項對應一個描述符和描述符指向的數據塊);同樣的,設備希望處理盡可能多的緩沖項然后再發送一個中斷。通過盡量處理更多的緩沖項的方式,來攤薄通知的代價。
這種策略是一種理想狀態,因為大多數時候驅動并不知道下一組緩沖項何時帶來,因此不得不每一組緩沖項準備好之后就必須要Kick設備。同樣的,設備在處理完相應的緩沖項之后,就盡快的發送中斷給驅動,以達到盡可能小的延遲。
如圖6所示,在設備模擬的虛擬化場景下,驅動可以暫時禁用中斷,設備也可以暫時禁用Kick。通過這樣的機制,可以最大限度的減少通知的代價,并且不影響性能和延遲。Virtio 1.1支持兩種通知抑制機制,因此共有三種模式:
使能通知模式:完全無抑制,使能通知;
禁用通知模式:如圖6所示,可以完全禁止對方發通知給自己;
使能特定的描述符通知模式:告知對方一個特定的描述符,當對方順序處理到此描述符處理完成時產生通知。
2.4 總結
如圖7,Virtio基于分層的設計思想,定義了三層Virtio設備架構:
最下層的總線接口。PCI是最常用的Virtio場景使用的總線,但Virtio協議不僅僅支持PCI,也支持MMIO和Channel IO等。
通用的Virtio交互接口。包括Virtqueue、功能特征位、配置空間等。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中pass though訪問硬件設備,某種程度上也可以認為是把運行在Hypervisor中的模擬設備 “卸載”到了硬件。因此,IO接口設備的卸載本質上和IO設備硬件虛擬化是一件事情。
如圖8,為了實現設備接口的標準化、加速IO處理的性能以及潛在的充分利用現有的虛擬化生態(例如更好的支持設備熱遷移)等原因,阿里云在神龍芯片里實現了硬件的Virtio接口設備,通過Virtio接口設備支持Virtio-net網絡驅動和Virtio-blk存儲驅動等,實現了類虛擬化IO設備Virtio的硬件“卸載”。
AWS的NITRO系統支持網絡、本地存儲和遠程存儲,NITRO實現了網絡接口設備ENA/EFA(AWS自定義接口)的硬件“卸載”以及存儲接口設備NVMe(遠程存儲EBS使用的是NVMe接口,本地存儲也是NVMe接口)的卸載。
b. 接口設備卸載后的遷移問題
當把設備“卸載”到硬件,讓VM直接訪問硬件設備,這使得VM的設備熱遷移變的非常有挑戰。vDPA(vhost Data Path Acceleration,vhost數據路徑加速,其中vhost是Virtio后端設備模擬的輪詢方式實現)實現了一種折中的解決方案,如圖9所示,vDPA把Virtio分為了控制面和數據面:
控制面。vDPA控制面依然是通過要經過Hypervisor的處理,用于設備和VM之間的配置更改和功能協商,用于建立和終止數據面。
數據面。vDPA數據面包括共享隊列以及相應的通知機制,用于在設備和VM之間傳輸實際的數據。
使用vDPA一個重要原因是,在熱遷移的時候可以很方便的把Virtio數據面的處理切換回傳統的Virtio/Vhost后端設備模擬。這樣,可以充分利用現有的基于KVM/Qemu對Virtio設備遷移的解決方案來完成設備的遷移。
c. 虛擬化管理的卸載
從軟件虛擬化進化到硬件虛擬化的過程,本身就可以看作是一個硬件加速以及硬件卸載的過程。我們逐步的剝離了Hypervisor的功能,比如通過VT-x技術“卸載”了Hypervisor的CPU/內存等的軟件模擬,以及通過VT-d以及vDPA等技術“卸載”了設備軟件模擬。這些剝離,使得Hypervisor越來越輕量,整個系統的虛擬化開銷也越來越少。進一步的,我們可以把虛擬化的管理(例如Linux平臺主流的管理程序Libvirt)卸載到硬件中的嵌入式軟件運行。
如圖10, 我們通過橋接的方式,實現主機軟件和硬件中嵌入式軟件通信機制。把虛擬化管理等軟件任務從主機卸載到嵌入式系統(依然有很小一部分任務無法卸載,如虛擬機資源分配、vCPU調度等)。這樣,可以把幾乎100%的主機資源提供給用戶,使用戶虛擬機得到近乎物理機的性能。
通過虛擬化管理卸載到硬件中的嵌入式CPU軟件,我們可以做到物理上的業務和管理分離,整個業務主機跟云計算管理網絡安全的隔離,只能通過特定的接口訪問到Lite Hypervisor,除此之外,不能訪問主機的任何資源。這樣,即使有潛在的運維操作失誤,也無法對業務主機造成影響。
責任編輯:haq
-
虛擬化
+關注
關注
1文章
366瀏覽量
29774 -
APIC
+關注
關注
0文章
4瀏覽量
7242
原文標題:技術分享 | I/O虛擬化及Virtio接口介紹
文章出處:【微信號:Ithingedu,微信公眾號:安芯教育科技】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論