VFIO概述


VFIO(Virtual Function IO)研究

主要研究VFIO在虛擬化中的應用,但VFIO的應用不止於虛擬化.

VFIO的全稱是Virtual Function IO,但這個名字並不能反應它的特點,以下兩個假名字更能反應VFIO的特點:

  1. Very Fast IO

由於VFIO是將設備直接透傳給虛擬機,所以Guest中與該設備相關的IO性能會大幅提高,接近native性能.

  1. Versatile Framework for userspace IO

這個名字反映了VFIO的功能,即能夠將device安全地映射到用戶空間,使用戶能夠對device進行操作.

研究目的

研究利用-device vfio-pci的方式將PCI透傳到虛擬機中后,在虛擬機中訪問PCI設備的配置空間,MMIO寄存器,IO Port的流程是怎樣的.

VFIO原理

VFIO把設備通過IOMMU映射的DMA物理內存地址映射到用戶態中,讓用戶態程序可以自行操縱數據的傳輸,還可以自行注冊中斷處理函數,從而在用戶態下實現設備的驅動程序.

因此VFIO的基礎是IOMMU.

IOMMU


基礎功能

  • 地址翻譯

IOMMU可以將能直接訪問memory的IO總線(DMA–capable)連接到RAM中.

與傳統的MMU功能類似,MMU能將CPU使用的虛擬地址轉化為物理地址,而IOMMU能將device使用的虛擬地址(也稱為設備地址或者IO地址)轉化為物理地址.

如果沒有IOMMU,DMA也能直接訪問RAM中的內容,但是讓DMA沒有限制地訪問RAM是一件很危險的事情,而IOMMU能夠對這個過程加以限制,當DMA訪問的地址合法時,IOMMU才返回正確的數據.

  • 硬件中斷重映射

除了翻譯地址的功能,IOMMU還能對硬件中斷進行重映射,達到屏蔽部分中斷,或自定義中斷處理函數的目的.

設備隔離

基於地址翻譯和硬件中斷重映射兩大功能,IOMMU就具有了隔離設備的能力,這提高了設備訪問RAM時和設備發出中斷時的安全性.

除了將單個設備隔離的功能外,IOMMU還能隔離一組設備,如隔離PCI橋上的幾個設備,所以IOMMU還有一個概念,叫做IOMMU_GROUP, 代表一組被隔離的設備的集合.

通過把host的device和對應driver解綁,然后綁定在VFIO的driver上,就會在/dev/vfio/目錄下出現一個group,這個group就是IOMMU_GROUP號,如果需要在該group上使用VFIO,需要將該group下的所有device與其對應的驅動解綁.


VFIO Container

在IOMMU_GROUP的基礎上,VFIO封裝了一層Container Class,Container的作用是,當我們想在不同的IOMMU_GROUP之間共享TLB和page tables(用於地址翻譯的頁表)時,就將這些group放到同一個container中,因此Container可以看做是IOMMU_GROUP的集合.

虛擬化中VFIO的應用

這里演示一個將網卡設備利用VFIO透傳到虛擬機中的例子.需要注意的是,利用VFIO將PCI設備透傳到虛擬機之后,Host將無法使用該設備.

虛擬機默認網卡

首先利用默認qemu選項啟動虛擬機后,查看lspci的輸出,看看虛擬機默認使用的網卡是什么?

可以看到虛擬機默認的網卡是Intel的82540EM,是由Qemu-kvm軟件模擬出來的一款網卡.

將Host的PCI網卡透傳到虛擬機

首先在Host上使用lspci查看擁有的PCI網卡型號,可以看到Realtek的一款網卡,該網卡的PCI標記為06:00.0.

要使用VFIO,必須在Linux啟動時添加啟動項intel_iommu=on,因為VFIO的底層依賴IOMMU.

  • 加載VFIO-PCI module
sudo modprobe vfio-pci

如果加載成功,可以在dmesg中看到相關log.

  • 查看網卡所在的IOMMU Group
$ readlink /sys/bus/pci/devices/0000:06:00.0/iommu_group
../../../../kernel/iommu_groups/3

可以看到該Realtek網卡位於iommu_group的group3.

  • 查看設備所在iommu_group的所有設備
$ ls /sys/bus/pci/devices/0000:06:00.0/iommu_group/devices/
0000:00:05.0  0000:00:05.1  0000:06:00.0

可以看到在iommu_group3中,除了該Realtek網卡,還有2個設備.

  • 將設備與對應的驅動解綁

為了將設備透傳到虛擬機中,需要將設備與其對應的驅動解綁,這樣該設備就可以使用VFIO的驅動了.注意,不僅要將要透傳的設備解綁,還要將與設備同iommu_group的設備都解綁,才能透傳成功.

$ echo 0000:06:00.0 | sudo tee /sys/bus/pci/devices/0000:06:00.0/driver/unbind
0000:06:00.0
$ echo 0000:00:05.0 | sudo tee /sys/bus/pci/devices/0000:00:05.0/driver/unbind
0000:00:05.0 
$ echo 0000:00:05.1  sudo tee /sys/bus/pci/devices/0000:00:05.1/driver/unbind
0000:00:05.1
  • 查看設備的Vendor和DeviceID
$ lspci -n -s 06:00.0
06:00.0 0200: 10ec:8168 (rev 15)

可以看到該Realtek網卡的Vendor為10ec,DeviceID為8168.

  • 將設備綁定到vfio-pci module
$  echo 10ec 8168 | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
10ec 8168

可以通過ls /dev/vfio查看是否綁定成功,如果綁定成功,/dev/vfio目錄下會出現該device所屬的iommu_group號.

這里的3就是我們要透傳的Realtek網卡所在的iommu_group號.

  • 啟動虛擬機
$ sudo x86_64-softmmu/qemu-system-x86_64 -m 4096 -smp 4 -hda ~/ewan/Workspace/img/Ubuntu18.04_loop.img -enable-kvm -cpu host -device vfio-pci,host=06:00.0

這里我使用的是從源碼編譯的qemu,但是從apt-get安裝的的qemu也是可以的.

進入guest之后運行lspci,可以看到相比之前的PCI設備,多了一個Realtek網卡,這個網卡和host上的信息一模一樣,證明將網卡透傳到Guest成功!.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM