PCI设备与UIO驱动

2023-10-17 23:12
文章标签 驱动 设备 pci uio

本文主要是介绍PCI设备与UIO驱动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

随着网络的高速发展,对网络的性能要求也越来越高,DPDK框架是目前的一种加速网络IO的解决方案之一,也是最为流行的一套方案。DPDK通过bypass内核协议栈与内核驱动,将驱动的工作从内核态移至用户态,并利用polling mode的线程工作模式加速网络I/O使得网络IO性能出现大幅度的增长。

  在使用DPDK的时候,我们常常会说提到用DPDK来接管网卡以达到bypass内核驱动以及内核协议栈的操作,本篇文章将主要分析DPDK是如何实现的bypass内核驱动来实现所谓的“接管网卡”的功能。

注意:

  1. 本篇文章会涉及一些pci设备的内容,但是不会重点讲解pci设备,pci设备中的某些规则就是这么设计的,并没有具体原因。
  2. 本篇部分原理的讲解会以Q&A的方式拖出,因为DPDK bypass内核的这部分涉及的知识维度比较多,没有办法按照线性的思路讲解。
  3. 本人能力以及水平有限,没办法保证没有疏漏原创内容
  4. 由于内容过多,本篇文章会着重基础的将PCI以及igb_uio相关的知识与分析,以便于不光是从DPDK本身,而是全面的了解DPDK如果做到的bypass内核驱动,另外关于DPDK的代码部分实现将会放在后续文章中放出,另外还有DPDK的中断模式以及vfio也会在后续的文章中依次发出(先开个坑,立个flag)

【1.谈一谈使用】

  通常启动一个基于dpdk开发的应用,都需要几步准备来完成。

  1. 首先需要插入igb_uio/vfio-pci这两个驱动中的一个,接下来会以igb_uio为例讲解(因为简单...vfio还是有点复杂的...vfio的解析会放在以后的文章中放出)。
  2. 其次需要运行dpdk-devbinds.py这个dpdk官方给出的py脚本,以此来完成内核驱动到igb_uio/vfio的接管。接管之后,再次运行dpdk-devbinds可以很明显的看到驱动从ixgbe转为了igb_uio。请见图1.
  3. 运行dpdk应用,以-p参数指定要接管的网口,例如-c 0x03,那么接管的网口便是port 0和port 1.

图1.接管前后pci设备驱动发生的变化

  那么经过上述三个操作,至少脑子里会产生这么几个问题:

  Q:igb_uio/vfio-pci的作用是什么?为什么要用这两个驱动?这里的“驱动”和dpdk内部对网卡的“驱动”(dpdk/driver/)有什么区别呢?

  Q:dpdk-devbinds是如何做到的将内核驱动解绑后绑定新的驱动呢?

  Q:dpdk应用内部是如何操作pci设备的呢?是怎么让pci设备可以将数据包直接扔到用户态的呢?

  这三个问题,实际上也是我当初在研究这一部分是遇到的三个问题。首先我们先来看第一个问题。

【问题一:igb_uio/vfio-pci是什么?】

  我们会以igb_uio驱动为例进行讲解。这里其实很难一步讲清楚igb_uio的作用以及实现原理,所以接下来的讲解还是会以Q&A和“挖坑式”的方式进行逐步将原理展现给各位看官面前。先说说操作一个外设,最先想到的是什么呢?如果有过单片机等嵌入式外设开发的朋友肯定会冒出这样的一个想法

我得配置这个外设,为此我需要找到它的寄存器,但是找到它的寄存器前提是我得先拿到基地址才行, 接下来通过基地址+寄存器偏移就能找到寄存器所在的地址,然后就可以配置了

  所以第一个任务便是我们要拿到”基地址“,首先有必要先科普一下pci设备的基地址。因此我必须得掏出一张图,即描述pci配置空间的一张图,如果图2所示。

图2.pci设备的配置空间

  图2为pci配置空间的分布图,在图中,0x0010 ~ 0x0028这24个字节中,分布着6个PCI BAR(base address register),也就是最最重要的“基地址”,那这里有人可能会想问“这个图和我们有关系么?这个图中的空间在哪?我们该怎么解析?”,答案是“无关”,这些图中的信息事实上在系统启动时,就已经被解析完成了,以文件系统的方式供用户态程序取读取。但是这里其实有这样的一个问题:

PCI设备为啥有6个BAR,而不是3个、8个?这些BAR都有啥区别?实际访问寄存器的时候以哪一个BAR为基准呢?

  其实解释这个问题,是一件简单而又不简单的事情。简单是因为pci设备规定就是有6个bar空间,而不简单是因为不知道为什么规定6个bar空间。那么这些BAR又有什么区别呢?这里要引用一下stackoverflow上面一位老哥说的话,见图3.(这里其实我之前也一直不太明白,因为国内的很多论坛帖子都是千篇一律...很难筛选出自己想要的信息...)

图3.不同BAR空间的区别之StackOverflow

  其实关键就是蓝色的那句话,即”6个槽(BAR)允许设备以不同的目的提供不同的区域“,根据这个线索,我们来看一下intel 82599这款经典的10G网卡的datasheet中9.3.6中的解释。见图4.

图4.intel 82599 datasheet中关于不同pci bar的划分

  可以看到这款经典网卡(其实intel的卡基本都是这么分的)主要将6个pci bar分成了三块区域:

  • Memory BAR : 内存BAR,Memory BAR标志着这块BAR空间位于内存空间,通过mmap映射后可以直接访问。
  • I/O BAR : IO BAR空间,I/O BAR标志着这块BAR空间位于IO空间,对其的访问不能像Memory BAR那样映射之后就可以随心所欲访问,IO BAR必须通过专门的操作来进行读写。
  • MSI-X BAR : 这个BAR空间主要是用来配置MSI -X 中断向量。

  那么这里可能有人会问,一共不是6个BAR空间么?这里只分了3个区域,那么每个区域分多少呢?这里请注意的是关于图3中6个PCI BAR,每个PCI BAR都是32位的,但是像82599这种工作在64位的网卡,其实就只有三个BAR。BAR0 BAR1为Memory BAR,BAR2 BAR3为I/O BAR,BAR4 BAR5为MSI-X BAR。这里我们可以对照一款低端网卡I350的datasheet,见图5.

图6.I350网卡datasheet中关于BAR分布的描述

   从图6可以看到,对于I350这种低端的千兆网卡,可以将其配置位工作在32位还是64位模式下,但是对于82599这种万兆10g的卡,就没那么多选择余地了,只能工作在64位模式下,因此回到图3中,我们可以根据intel 82599的datasheet来得知intel的64bit网卡的bar分布是长什么样子的,如图7.

图7.intel 82599网卡的BAR分布

  所以PCI配置空间的规范结合intel的I350和82599这两款网卡的datasheet进行分析,我们可以得出这样的一个结论:”PCI有6个BAR是规范,6个BAR的区别和作用取决于具体的PCI外设,需要查看datasheet才能给出答案“。

  说完6个BAR的作用以及分布,接下来还有个问题,实际访问PCI BAR的时候以哪一个BAR为基准呢?这里主要有疑问的地方会出现在Memory BAR还是I/O BAR。因为需要搞清楚这两者的区别,才能真正判断在哪个BAR写配置。关于IO BAR和Memory BAR的区别首先需要科普一下,在x86体系架构下,内存的编址情况。接下来进入科普时间。

  其实这里是比较晦涩难懂的,首先我们得知道,为什么会出现I/O空间和外设空间?在讨论区别之前我们可以看一张图,看看I/O空间和Memory空间长什么样子,这里可以看宝华叔经典的《Linux设备驱动开发详解》的第11章部分,这里我就简单的说一下,x86下的I/O空间和Memory空间到底长啥样子。见图8.

图8.I/O空间与内存空间,来自宝华叔的《Linux设备驱动开发详解》中第11章

  另外需要注意的时,非x86体系架构下,例如ARM、PowerPC这些架构下,所有的外设和主存(RAM)都会进行统一的编址,所以kernel可以像访问正常的内存空间一样访问内设。而x86体系架构下,外设是进行独立编址的,如图8所示,因此也就出现了IO空间和Memory空间的区别。(其实可以将RAM看成一种”专门用来内存映射的IO设备“)。另外我们从图8还可一看到另外一个信息,那

这篇关于PCI设备与UIO驱动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/228588

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑燃料电池和电解槽虚拟惯量支撑的电力系统优化调度方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源程序擅长文章解读,论文与完整源程序,等方面的知识,电网论文源程序关注python

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件

麒麟系统安装GPU驱动

1.nvidia 1.1显卡驱动 本机显卡型号:nvidia rtx 3090 1.1.1下载驱动 打开 https://www.nvidia.cn/geforce/drivers/ 也可以直接使用下面这个地址下载 https://www.nvidia.com/download/driverResults.aspx/205464/en-us/ 1.1.3安装驱动 右击,

windows10 卸载网络驱动以及重新安装

右键桌面此电脑的图标,点击管理,设备管理器—网络适配器,找到下图中的驱动(不同的系统或者显卡会导致网卡驱动名称与下图不一样,多为Realtek开头),右键选择卸载设备,然后重启电脑,系统会自动重新安装驱动 新电脑首次安装驱动: 根据主板厂家,比如华硕,进入华硕官网,点击服务支持,点击下载中心,选择型号,点击右侧驱动程序和工具软件,选择windows版本,下载相应的驱动,下载完之后在对应文件中找