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成功!.



本文作者:EwanHai
本文链接:

https://www.cnblogs.com/haiyonghao/p/14440944.html
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
虚函数是面向对象编程中的概念,它允许在基类中声明一个函数,在派生类中进行重写。通过使用虚函数,可以实现多态性,即在运行时根据对象的实际类型来调用对应的函数。 在C++中,通过在基类的成员函数前面加上关键字"virtual"来声明一个虚函数。派生类可以重写基类中的虚函数,并使用相同的函数签名来定义自己的实现。当通过基类指针或引用调用虚函数时,程序会根据实际对象的类型来调用对应的重写函数。 例如,假设有一个基类Animal和派生类Dog和Cat,它们都有一个虚函数speak()。在基类Animal中,我们可以声明这个函数为虚函数,然后在派生类中分别重写它,使得不同的动物可以发出不同的声音。 ```cpp class Animal { public: virtual void speak() { cout << "Animal speaks!" << endl; } }; class Dog : public Animal { public: void speak() override { cout << "Dog barks!" << endl; } }; class Cat : public Animal { public: void speak() override { cout << "Cat meows!" << endl; } }; int main() { Animal* animal1 = new Dog(); Animal* animal2 = new Cat(); animal1->speak(); // Output: "Dog barks!" animal2->speak(); // Output: "Cat meows!" delete animal1; delete animal2; return 0; } ``` 在上面的例子中,通过基类指针animal1和animal2分别指向Dog和Cat对象,然后调用它们的虚函数speak()。由于speak()函数是虚函数,所以程序会根据实际对象的类型来调用相应的重写函数,输出不同的结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值