pcie SRIOV linux 调用流程

pcie SRIOV linux 调用流程背景当前的 I O 虚拟化技术有其优点和缺点 没有一个是基于任何行业标准的 业界认识到可替代架构的问题 并正在开发可共享的新设备 这些设备复制每个 VM 所需的资源 以便直接连接到 I O 设备 这样就可以在不涉及 VMM 的情况下进行数据移动 本机共享设备通常为它们公开的每个接口提供惟一的内存空间 工作队列 中断和命令处理 同时利用主机接口背后的公共共享资源 这些共享资源仍然需要进行管理 通常将一组管理寄存器公开给 VMM 中的可信分区 见图 1 Figure1 NativelyandS

背景

1.1 SR-IOV Goals

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

1.2 SR-IOV概述

支持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命令来创建磁盘等。












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/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:
通过下面的命令来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_IOV if (num_vfs == 0) return igb_pci_disable_sriov(dev); else return igb_pci_enable_sriov(dev, num_vfs); #endif return 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 VFs rc = 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); 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/203850.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午9:27
下一篇 2026年3月19日 下午9:28


相关推荐

  • webstorm 19 激活码【2021最新】

    (webstorm 19 激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月27日
    71
  • matlab初学者入门_什么一闻就能睡2小时

    matlab初学者入门_什么一闻就能睡2小时目录零基础入门matlab前言1.界面认识2.变量命名3.数据类型4.元胞数组和结构体5.矩阵操作6.程序结构7.基本绘图操作7.1.二维平面绘图7.2.三维立体绘图8.图形的保存与导出9.补充零基础入门matlab前言这篇文章很适合MATLAB的入门学习,这也是我在入门时学习的笔记。虽然说是”零基础“入门matlab,但是如果有其它编程语言基础的话,学起来自然会更轻松。特别鸣谢:B站UP主——爱研究的小阿楠1.界面认识2.变量命名注:Matlab中的注释%%独占一行的注释(有上下横线

    2025年12月6日
    9
  • Tomcat配置appBase为空时BlazeDS找不到endpoint路径[通俗易懂]

    因为有用quartz定时任务,把tomcat的appBase设置为空,以防同时执行2次。但这样BlazeDS初始化时会找不到endpoint路径。 解决方法是把endpointurl中的{context.root}全部改为项目的路径,如项目是webapps\abc,就把所有{context.root}改为abc…

    2022年4月15日
    54
  • 思科九年pdf_思科中国网站

    思科九年pdf_思科中国网站第1节:思科九年(1)  序  南半球的二月是盛夏。这里白天的阳光炽烈而持久,四处都是耀眼的惨白。电视里的广告说皮肤癌是这个国家的国癌,提醒人们小心这厉害的阳光:要穿长袖的衣服待在阴凉的地方,要戴墨镜涂防晒霜。即便如此,海边的沙滩上还是躺满了裸露大片皮肤晒日光浴的各色人种。他们慵懒地躺着趴着,戴着墨镜看书或者睡觉。他们的孩子在水边嬉戏,他们的狗在四处奔跑。海浪一层层涌来,冲浪者和他们的冲浪

    2022年8月21日
    9
  • 腾讯元宝如何用excel生成图表

    腾讯元宝如何用excel生成图表

    2026年3月13日
    5
  • CentOS7安装mysql5.5

    CentOS7安装mysql5.5一、检查本地是否安装过其他版本的mysqlrpm-qa|grep-i mysql由于有些版本自带的有mariadb,检查是否有mariadb,若是有需要先卸载 yum-yremovemaria*二、下载mysql5.5的服务器和客户端的安装包 下载服务器包:wget https://dev.mysql.com/get/Downloads/MySQ…

    2022年5月4日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号