背景

当前的I/O虚拟化技术有其优点和缺点。没有一个是基于任何行业标准的。
业界认识到可替代架构的问题,并正在开发可共享的新设备。这些设备复制每个VM所需的资源,以便直接连接到I/O设备,这样就可以在不涉及VMM的情况下进行数据移动。

本机共享设备通常为它们公开的每个接口提供惟一的内存空间、工作队列、中断和命令处理,同时利用主机接口背后的公共共享资源。这些共享资源仍然需要进行管理,通常将一组管理寄存器公开给VMM中的可信分区。见图1。

Figure 1. Natively and Software Shared

通过拥有独立的工作队列和命令处理,这些设备能够同时接收来自多个源的命令,并在将它们传递到次要结构(例如,以太网或SAS链接)之前将它们合并在一起。虚拟化软件不再需要将I/O请求多路复用到串行流中。
本地共享设备可以通过多种方式实现,包括标准化的和专有的。由于大多数这些设备是通过PCI访问的,PCI- SIG决定创建一个标准方法。PCI-SIG SR-IOV规范定义了创建本机共享设备的标准化机制。
图1显示了一个可能的示例配置,其中三个虚拟机通过虚拟函数原生(直接)访问以太网控制器中的专用资源,同时物理函数也有自己的资源。

1.1 SR-IOV Goals

PCI-SIG SR-IOV规范的目标是通过为每个虚拟机提供独立的内存空间、中断和DMA流来标准化绕过VMM参与数据移动的方法。SR-IOV体系结构的设计目的是允许设备支持多个虚拟功能(VFs),并将大量注意力放在最小化每个附加功能的硬件成本上。
SR-IOV引入了两种新的函数类型:

  1. 物理功能(PFs):这些是完整的PCIe功能,包括SR-IOV扩展功能。该功能用于配置和管理SR-IOV功能。
  2. 虚拟功能(VFs):这些是“轻量级”PCIe函数,包含数据移动所需的资源,但配置资源的集合被精心最小化。

1.2 SR-IOV概述

虚拟化的直接分配方法提供了非常快的I/O。但是,它阻止了I/O设备的共享。SR-IOV提供了一种机制,通过这种机制,单个根函数(例如单个以太网端口)可以看起来是多个独立的物理设备。
能够支持SR-IOV的设备可以配置(通常由VMM配置),使其在PCI配置空间中作为多个功能出现,每个功能都有自己的配置空间,带有基址寄存器。VMM通过将实际配置空间VFs映射到VMM提供给虚拟机的配置空间,将一个或多个VFs分配给VM。参见图2。

Figure 2. Mapping VF Configuration

支持SR-IOV的设备提供许多可配置的独立VFs,每个VFs都有自己的PCI配置空间。VMM将一个或多个VF分配给虚拟机。内存转换技术,如Intel®VT-x和Intel®VT-d提供硬件辅助技术,允许直接DMA传输到和从VM,从而绕过VMM的软件切换。

2.2 SR-IOV 的条件

硬件条件:
1. CPU 支持 Intel VT-x 和 VT-D (或者 AMD 的 SVM 和 IOMMU)
2. 有支持 SR-IOV 规范的设备:目前这种设备较多,比如Intel的很多中高端网卡等。
3. CPU必须支持IOMMU(比如英特尔的 VT-d 或者AMD的 AMD-Vi,Power8 处理器默认支持IOMMU),并且在BIOS中已开启。
4. 支持PCI-SIG* Single Root I/O Virtualization and Sharing(SR-IOV),并且在BIOS中已开启。
软件条件:
  1. 需要 QEMU/KAM 的支持。
  2. 安装软件包
    yum install -y kvm virt-* libvirt bridge-utils qemu-img
    kvm:软件包中含有KVM内核模块,它在默认linux内核中提供kvm管理程序
    libvirts:安装虚拟机管理工具,使用virsh等命令来管理和控制虚拟机。
    bridge-utils:设置网络网卡桥接。
    virt-*:创建、克隆虚拟机命令,以及图形化管理工具virt-manager
    qemu-img:安装qemu组件,使用qemu命令来创建磁盘等。

查看系统是否支持虚拟化,egrep -c ‘(vmx|svm)’ /proc/cpuinfo
大于1表示开启了,等于0表示没开启,如果没开启则需要在BIOS中开启intel VT-d
查看kvm模块是否被加载lsmod |grep kvm,如果有信息,则表示加载成功。
Centos系统默认没有启动IOMMU功能,在grub文件的GRUB_CMDLINE_LINUX后面添加intel_iommu=on
检测是否生效 sudo virt-host-validate

RedHat Linux 官方提供了详细的流程:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/virtualization_host_configuration_and_guest_installation_guide/index

网上这方面资料还是比较多的:
https://www.cnblogs.com/sammyliu/p/4548194.html

https://www.cnblogs.com/liuhongru/p/11068460.html

https://blog.csdn.net/u010443710/article/details/104756445?utm_medium=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.edu_weight

3.0 kernel 代码流程

查看是否支持SR-IOV:

lspci -vvs bus:dev.fun, 如果有类似下面的capability,说明支持SR-IOV, 并能看出来支持几个VFs等详细信息。

通过下面的命令来enable SRIOV功能:

echo 2 > /sys/bus/pci/devices/0000:5e:00.0/sriov_numvfs
上面红色的是一个支持SR-IOV功能的pcie 网卡,2是enable的数量,从下图看,enable了2个VFs后,多出来了2个pcie设备。

enable SR-IOV的流程:

从上面命令上看,入口是每个pcie的sriov_numvfs节点,下面是实现节点的代码:

/** num_vfs > 0; number of VFs to enable* num_vfs = 0; disable all VFs** Note: SRIOV spec doesn't allow partial VF*       disable, so it's all or none.*/
static ssize_t sriov_numvfs_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{struct pci_dev *pdev = to_pci_dev(dev);int ret;u16 num_vfs;ret = kstrtou16(buf, 0, &num_vfs);if (ret < 0)return ret;if (num_vfs > pci_sriov_get_totalvfs(pdev))return -ERANGE;device_lock(&pdev->dev);if (num_vfs == pdev->sriov->num_VFs)goto exit;/* is PF driver loaded w/callback */if (!pdev->driver || !pdev->driver->sriov_configure) {pci_info(pdev, "Driver doesn't support SRIOV configuration via sysfs\n");ret = -ENOENT;goto exit;}if (num_vfs == 0) {/* disable VFs */ret = pdev->driver->sriov_configure(pdev, 0);goto exit;}/* enable VFs */if (pdev->sriov->num_VFs) {pci_warn(pdev, "%d VFs already enabled. Disable before enabling %d VFs\n",pdev->sriov->num_VFs, num_vfs);ret = -EBUSY;goto exit;}ret = pdev->driver->sriov_configure(pdev, num_vfs);if (ret < 0)goto exit;if (ret != num_vfs)pci_warn(pdev, "%d VFs requested; only %d enabled\n",num_vfs, ret);exit:device_unlock(&pdev->dev);if (ret < 0)return ret;return count;
}

从上面看,支持SR-IOV的driver需要实现下面的函数接口

static struct pci_driver igb_driver = {.name     = igb_driver_name,.sriov_configure = `igb_pci_sriov_configure`, / 支持sriov功能需要实现的函数 /
};static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
{#ifdef CONFIG_PCI_IOVif (num_vfs == 0)return igb_pci_disable_sriov(dev);elsereturn igb_pci_enable_sriov(dev, num_vfs);
#endifreturn 0;
}

最终调用的是pci api: pci_enable_sriov

/*** pci_enable_sriov - enable the SR-IOV capability* @dev: the PCI device* @nr_virtfn: number of virtual functions to enable** Returns 0 on success, or negative on failure.*/
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
{might_sleep();if (!dev->is_physfn)return -ENOSYS;return sriov_enable(dev, nr_virtfn);
}

下面详细分析下sriov_enable

sriov_enable(struct pci_dev *dev, int nr_virtfn)pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);这里省略数行,主要是用来判断initial,total_VFs,nr_virtfn是否合法bus = pci_iov_virtfn_bus(dev, nr_virtfn - 1); //计算出来一个bus num分给VFs使用dev->bus->number + ((dev->devfn + dev->sriov->offset + dev->sriov->stride * vf_id) >> 8); pci_enable_resources(dev, bars);//设置VFs 配置空间的PCI_COMMAND字段pcibios_sriov_enable(dev, initial);pci_iov_set_numvfs(dev, nr_virtfn);/设置VFs number,读取offset,stride/iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);/ VF Enable, VF Memory Space Enable/sriov_add_vfs(dev, initial);for (i = 0; i < num_vfs; i++) //逐个初始化,add VFsrc = pci_iov_add_virtfn(dev, i); //和pcie初始化的流程基本一致,分配填充结构体,初始化设备,add 设备virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id));virtfn = pci_alloc_dev(bus);virtfn->devfn = pci_iov_virtfn_devfn(dev, id);virtfn->vendor = dev->vendor;virtfn->device = iov->vf_device;virtfn->is_virtfn = 1;virtfn->physfn = pci_dev_get(dev);if (id == 0)pci_read_vf_config_common(virtfn);pci_setup_device(virtfn); //这两个函数就是按照capability初始化设备中间省掉获取bar空间的代码,从PF上的SR-IVO的bar空间获取pci_device_add(virtfn, virtfn->bus);sprintf(buf, "virtfn%u", id);rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn");                 kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);pci_bus_add_device(virtfn)kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);

pcie SRIOV linux 调用流程相关推荐

  1. linux内核定时器死机,浅析linux内核中timer定时器的生成和sofirq软中断调用流程

    浅析linux内核中timer定时器的生成和sofirq软中断调用流程 mod_timer添加的定时器timer在内核的软中断中发生调用,__run_timers会spin_lock_irq(& ...

  2. Linux ALSA声卡驱动之七:录音(Capture) 调用流程

    ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...

  3. 从零开始之驱动发开、linux驱动(十一、linux的中断框架和详细调用流程)

    上一节我们学习了在linux中,中断的初始化流程以及调用流程. 本节我们对中断的框架进行说明. 开始之前我们先把前面说过的一个数据结构拿出来分析一下. 1.中断描述符 /*** struct irq_ ...

  4. Linux USB HUB识别usb设备调用流程

    插入usb设备通过dmesg查看内核打印信息 查看内核源码的调用流程

  5. java 操作uart串口_【tty】应用程序调用write写串口调用流程

    这几天在跟进串口使能流控后收发异常问题,特简单梳理了下应用程序执行write操作的调用流程,在这简单记录下,平台为全志方案 tty_io.c         tty_io.c              ...

  6. EBB-11、Linux启动流程

    一.Linux开机流程 (一)power on 开机后加载BIOS(Basic Input Output System,基本的输入输出系统),BIOS加载 CMOS中所存放的当前主机各项硬件配置.系统 ...

  7. Linux 系统启动流程及其介绍

    熟悉Linux系统启动流程可以更好的排除Linux系统在启动的过程中所遇到的错误,下面介绍Linux系统在启动过程. 开机,BIOS自检:检测外置设备,目的是为了把外围设备的信息提供给操作系统使用 寻 ...

  8. Linux 进内核,arm linux 启动流程之 进入内核

    原标题:arm linux 启动流程之 进入内核 还是从编译链接生成vm 的过程来看吧,由一大堆.o文件链接而成,第一个就是 kernel/arch//kernel/head-armv.o ,而且我们 ...

  9. Linux 启动流程学习

    Linux 启动流程学习 开机自检(加载BIOS) 无论什么机器,在开机后都要进行通电自检(硬件),如果硬件有问题,则无法继续下去. (例如当内存条松动时或者损坏,就会发出嘀嘀嘀警报声).接着开始加载 ...

最新文章

  1. linux python3安装包_Linux下安装python3及相关包
  2. python封装enclosure
  3. 码长6075的qc-ldpc编译码的MATLAB误码率仿真
  4. 同IP不同端口Session冲突问题
  5. kafka修改分区数_ELK|kafka增加分区或调整副本数
  6. 20165305 第十周课下补做
  7. DB2添加数据时主键、唯一键冲突的解决方法
  8. 2002年4月计算机二级c语言题,全国计算机等级考试二级C语言真题2004年4月
  9. 人的差别在于业余时间——细细品味 ==程序员学习能力提升三要素 ==》程序员学习能力提升三要素 ==编程从业五年的十四条经验,句句朴实
  10. emu8086打印等腰三角形
  11. 全国计算机三级网络技术题库南开,计算机三级上机-适用于三级网络技术数据库等(南开100题).doc...
  12. 云服务器内存占用多少,腾讯云云服务器CPU或内存占用过高怎么办?
  13. “Microsoft C++ 异常: cv::Exception,位于内存位置 0x0000005C8ECFFA80 处。”
  14. sql函数—Lpad、Rpad
  15. rtx服务器插件的作用,腾讯通RTX手机版插件介绍 - 有度帮助中心
  16. (转载)深入了解iOS中的OOM(低内存崩溃)
  17. 火狐浏览器打开后是搜狗浏览器_搜狗浏览器和Firefox浏览器哪个好
  18. 巧设BIOS,让老主板也支持U盘启动!
  19. Python实现Chrome浏览器书签自动备份
  20. ####好好好#####知识图谱上的双塔召回:阿里的IntentGC模型

热门文章

  1. 产品在线测量系统方案
  2. mysql number函数_mysql有row_number函数吗?
  3. 如何进行有效的产品规划?
  4. 数据分析师做成了提数工程师,该如何破局?
  5. chrome 启动参数--user-data-dir 和 --profile-directory的关系
  6. windows批处理实现矩阵雨效果
  7. 卷积的物理意义(图解)
  8. 解决WSL Ubuntu20.4+xfce4 图形界面一段时间后黑屏
  9. 使用jieba分析小说太古神王中,男主更爱谁?去文章中找答案吧!
  10. SIT测试阶段bug修复流程管理