Anatoly Burakov:英特尔软件工程师,目前在维护DPDK中的VFIO和内存子系统。

“文章转载自DPDK与SPDK开源社区公众号”

目录

引言

环境抽象层(EAL)参数

IO虚拟地址(IOVA)模式

作为物理地址(PA)的IOVA模式

作为虚拟地址(VA)的IOVA模式

IOVA模式的选择

IOVA模式和DPDK PCI驱动程序

用户空间IO(UIO)驱动程序

VFIO内核驱动程序

内核驱动程序的选择

软件轮询模式驱动程序(PMD)

总结

推荐阅读

系列文章


名词缩写

  1. ASID:Address Space ID   地址空间标识符
  2. CD:Context Descriptor;  上下文描述符;
  3. CTP:Context-table pointer   上下文表指针
  4. EPT:Extended Page Table 扩展页表
  5. GPA:Guest Phyical Address   客人的实际地址
  6. GVA:Guest Virtual Address   访客虚拟地址
  7. HPA:Host Phyical Address    主机物理地址
  8. IOVA:IO Virtual Address space   IO虚拟地址空间
  9. IPA:Intermediate Phyical Address    中间物理地址
  10. NPT:Nested Page Table   嵌套页表
  11. PCID:Process context identifier 进程上下文标识符
  12. PMCG:Performance Monitor Counter Groups 性能监控计数器组
  13. S2TTB:Stage 2 Translate Table Base  第二阶段翻译表库
  14. SMMU:System MMU 系统MMU
  15. VT-d:Virtualization Technology for Direct I/O 直接I/O虚拟化技术

引言


上一篇中,我们介绍了数据平面开发工具包(DPDK)内存管理背后的主要概念和原理,也探讨了它们对DPDK拥有绝佳性能所做出的贡献。但是,DPDK远比这些概念与原理复杂,需要正确配置才能充分的利用系统的潜力。而其中,选择正确的内核驱动和IOVA模式可能是最为关键的,但这也取决于要运行的应用及其运行前的环境。本文将介绍可选的几种不同配置选项,并为读者日后的选择提供建议。

环境抽象层(EAL)参数


环境抽象层(EAL)是DPDK的核心。它是DPDK的一个库。顾名思义,它负责抽象出环境(硬件、操作系统等)并为软件提供统一的接口。EAL要处理很多东西,所以也不难理解为何它会是DPDK中最复杂的一个部分。由EAL负责处理的包括:

  • · 管理CPU核心和非统一内存访问(NUMA)节点
  • · 将硬件设备的寄存器映射到内存中,使它们可受DPDK轮询模式驱动程序(PMDs)驱动
  • · 管理硬件和软件中断
  • · 抽象出平台差异,如字节序、缓存行大小等
  • · 管理内存和多进程同步
  • · 提供与原子、内存屏障和其他同步原语共通的独立于平台和操作系统的方法
  • · 加载和枚举硬件总线,设备和PMD

以上只罗列了EAL的部分功能,但这足以体现它对于DPDK的重要性。因此,DPDK中大量配置与EAL有关也不足为奇。目前,可以通过(直接或间接地)为DPDK初始化例程指定命令行参数对EAL进行配置。DPDK应用命令行通常如下所示:

./app <EAL command-line   parameters> -- <application-specific command-line parameters>

某些使用DPDK的应用(如OvS-DPDK)可能会对用户隐藏此步骤,因此可能不需要明确指定EAL命令行参数,但尽管如此此步骤还是会在后台进行。

IO虚拟地址(IOVA)模式


DPDK是一个用户态应用框架,使用DPDK的软件可以像其他软件一样使用常规虚拟地址。但除此之外,DPDK还提供了用户态PMD和一组API,以实现完全以用户态执行IO操作。本系列的前一篇也已经提到过,硬件不能读取用户空间虚拟地址;它使用的是IO地址——物理地址(PA)或IO虚拟地址(IOVA)

DPDK API对物理和IO虚拟地址不作区分,即使不是由IO内存管理单元(IOMMU)提供VA部分,也都以IOVA来代表两种地址。

但DPDK却会区分物理地址用作IOVA的情况,和IOVA与用户空间虚拟地址匹配的情况。它们在DPDK API中被称为IOVA模式,可分为两种:作为PA的IOVA模式,和作为VA的IOVA模式。

作为物理地址(PA)的IOVA模式


作为PA的IOVA模式下,分配到整个DPDK存储区的IOVA地址都是实际的物理地址,而虚拟内存的分配与物理内存的分配相匹配。该模式的一大优点就是它很简单:它适用于所有硬件(也就是说,不需要IOMMU),并且它适用于内核空间(将真实物理地址转换为内核空间地址的开销是微不足道的)。实际上,这就是DPDK长期以来的运作方式,在很多方面它都被认为是默认的选项。  

然而,作为PA的IOVA模式也存在一些缺点。其中一个就是它需要根用户特权——如果无法访问系统的页面映射,DPDK就无法获取内存区域的真实物理地址。因此,如果系统中没有root权限,就无法以该模式运行。

图1.作为PA的IOVA模式。

作为PA的IOVA模式还有另外一个值得一提的限制——虚拟内存分配要遵循物理内存分配。这意味着如果物理内存空间被分段(被分成许多小段而不是几个大段)时,虚拟内存空间也要遵循同样的分段。极端情况下,分段可能过于严重,导致被分割出来物理上连续的片段数量过多,耗尽DPDK用于存储这些片段相关信息的内部数据结构,就会让DPDK初始化失败。

图2.作为PA的IOVA模式下PA分段示例。

应对这些问题,DPDK社区提出了解决方法。举例来说,一种减少分段影响的方式是使用更大的分页——问题虽然没被解决,但是单独的1千兆字节(GB)段比独立的2兆字节(MB)段能大幅度减小分段的数量。另外一种广泛使用的解决方式则是在启动时引导系统并保留大页,而不是在运行时。但上述的解决方法都不能根本地解决问题,而且整个DPDK社区都习惯了要去解决这些问题,每个DPDK用户(有意或无意)在使用时都会采取相同的思维模式——“我需要X MB内存,但以防万一,我要保留X + Y MB!”

作为虚拟地址(VA)的IOVA模式


相比之下,作为VA的IOVA模式不需遵循底层物理内存的分布。而是重新分配物理内存,与虚拟内存的分配匹配。DPDK EAL依靠内核基础设施来实现这一点。内核基础设施又反过来使用IOMMU重新映射物理内存。

图3.作为VA的IOVA模式。

这种方式的优点显而易见:作为VA的IOVA模式下,所有内存都是VA-和IOVA-连续的。这意味着所有需要大量IOVA连续内存的内存分配更有可能成功,因为对硬件来说,即使底层物理内存可能不存在,内存看上去还是IOVA连续的。由于重新映射,IOVA空间片段化的问题就变得无关紧要。不管物理内存被分段得多么严重,它总能被重新映射为IOVA-连续的大块内存。

图4.作为VA的IOVA模式下的分段示例。

作为VA的IOVA模式还有另一个优点,它不需要任何权限。这是因为它不需要访问系统页面映射。这样就可以允许以非root用户身份运行DPDK,而且在特权访问不受欢迎的环境中,如云原生环境就可以更加容易地使用DPDK。

当然, 作为VA的IOVA模式也有一个缺点。出于各种原因,有时候可能不能选择使用IOMMU。这种情况可能包括:

  • · 硬件不支持IOMMU
  • · 平台可能本身就没有IOMMU(比如没有IOMMU模拟的VM)
  • ·软件设备(例如,DPDK的内核网络接口(KNI)PMD)不支持作为VA的IOVA模式
  • · 一些IOMMU(通常是模拟的IOMMU)的地址宽度可能有限,虽然这不妨碍用作VA的IOVA模式,但限制了其有效性
  • · 在非Linux *的操作系统上使用DPDK

但是,这些情况还是相对较少,绝大多数情况下,作为VA的IOVA模式都可以正常工作。

IOVA模式的选择


很多情况下,DPDK默认选择作为PA的IOVA模式,因为从硬件角度这是最安全的模式。所有给定的硬件(或软件)PMD至少都可以保证支持作为PA的IOVA模式。尽管如此,如果条件允许,还是强烈建议所有DPDK用户使用作为VA的IOVA模式,毕竟此模式具有不可否认的优势。

但是,用户不必非要在两者中选择一个。可以自动检测出最合适的IOVA模式,而且默认选项绝对适用于大多数情况,因此不需要用户来做此选择。如果默认选项并不合适,用户可以使用--iova-mode EAL命令行参数尝试使用EAL标志(适用于DPDK 17.11及更高版本)来代替IOVA模式:

./app --iova-mode=pa  # use IOVA as PA mode./app --iova-mode=va  # use IOVA as VA mode

大多数情况下,VA和PA模式不会互相排斥,可以使用任一模式,但在某些情况下,作为PA模式的IOVA是唯一可用的选择。当不能使用作为VA模式的IOVA时,即使EAL参数要求使用作为VA模式的IOVA,DPDK也会自动切换为作为PA模式的IOVA。

DPDK还提供了一个API,可查询运行时正在使用的IOVA模式,但通常这不会在用户应用中使用,因为只有像是DPDK PMD和总线驱动程序才会要求获取这种信息。

IOVA模式和DPDK PCI驱动程序


DPDK本身并不执行所有硬件设备寄存器和中断映射,它需要内核的帮助。为此,DPDK要使用的所有硬件设备都需要绑定到一个通用外围组件互连(Peripheral Component Interconnect, PCI)内核驱动程序。和一般的设备内核驱动程序不同的是,通用此驱动程序并未被锁定到特定的PCI ID集,即针对某类设备的常规驱动程序,可以与任何类型的PCI设备一起使用。

要将设备绑定到通用驱动程序,DPDK用户应该参考DPDK文档。该文档描述了在所有支持的操作系统中如何进行此项操作。但是,关于DPDK支持的各种用户态IO驱动程序及其支持的IOVA模式,还需要有所说明。虽然内核驱动程序和支持的IOVA模式之间看起来可能存在1:1的对应关系,但事实并非如此。下面的部分将讨论Linux上可用的驱动程序。

用户空间IO(UIO)驱动程序


DPDK代码库中最早的内核驱动程序是igb_uio驱动程序。在DPDK最初的发展阶段,这个驱动程序就已经存在了,因此它是DPDK开发人员使用最广泛也是最熟悉的驱动程序。

此驱动程序依赖内核用户空间IO(UIO)基础结构运作,并为所有中断类型(遗留、消息信号中断(MSI)和MSI-X)提供支持,以及创建虚拟功能。它还公开硬件设备通过/dev/uio文件系统注册和中断句柄,然后DPDK EAL将它们用于将它们映射到用户空间并使它们可用于DPDK PMD。

igb_uio驱动程序非常简单,能做的也并不多,因此它不支持使用IOMMU也就不足为奇了。或者,更确切地说,它确实支持IOMMU,但仅在传输模式下,它在IOVA和物理内存地址之间建立1:1映射。igb_uio不支持使用完整的IOMMU模式。因此, igb_uio驱动程序仅支持IOVA作为PA模式,并且根本无法在IOVA中作为VA模式工作。

类似于igb_uio的驱动程序在内核中可用:uio_pci_generic。它的工作方式与igb_uio非常相似,只是它的功能更加有限。例如,igb_uio支持所有中断类型(传统,MSI和MSI) -X),而uio_pci_generic只支持遗留中断。更重要的是,igb_uio可以创建虚拟函数(Virtual Function, VF),而uio_pci_generic则不能;因此,如果在使用DPDK物理函数(Physical Function, PF)驱动程序时创建VF是必需的一步,igb_uio是唯一的选择。

因此,在大多数情况下,igb_uio与uio_pci_generic相同或更可取。关于使用IOMMU的所有限制同样适用于igb_uio和uio_pci_generic驱动程序 - 它们不能使用完整的IOMMU功能,因此仅支持IOVA作为PA模式。

VFIO内核驱动程序


上述驱动程序的替代方案是vfio-pci驱动程序。它是虚拟功能I / O(VFIO)内核基础结构的一部分,并在Linux 3.6版中引入。VFIO基础设施使设备寄存器和设备中断可供用户空间应用程序使用,并可使用IOMMU设置IOVA映射以从用户空间执行IO。后一部分至关重要 - 此驱动程序专为与IOMMU一起使用而开发,在较旧的内核上,如果没有启用IOMMU,它甚至都无法工作。

与直观看法相反,使用VFIO驱动程序允许使用IOVA作为PA和IOVA作为VA模式。这是因为,虽然建议使用IOVA作为VA模式来利用该模式的所有好处,但没有什么能阻止DPDK的设置IOMMU映射的EAL以遵循物理内存布局1:1的方式;毕竟IOVA映射是任意的。在这种情况下,即使使用IOMMU,DPDK也可以在IOVA中作为PA模式工作,从而允许DPDK KNI等工作。但是,仍然需要root权限才能将IOVA用作PA模式。

在更新的内核(4.5+,向后移植到一些旧版本)上,有一enable_unsafe_noiommu_mode选项,允许在没有IOMMU的情况下使用VFIO。这种模式适用于与基于UIO的驱动程序相同的所有意图和目的,并具有所有相同的优点与限制。

内核驱动程序的选择


一般来说,在应用的角度我们并不需要选择内核驱动程序。通常来说,内核驱动程序的选择是由具体的情况来决定的。下面的流程图可以帮助决定在哪些特定情况下可以使用哪个驱动程序:

图5.通用PCI内核驱动程序选择流程图。

如图5所示,很明显应该在几乎所有的情况下都使用VFIO驱动程序,尤其是在生产环境中。IOMMU在硬件级别可提供设备隔离,这可以让使用DPDK的应用程序更加安全,而作为VA的IOVA模式则可以通过重新映射让内存得到更好的利用,而且不需要root权限来运行DPDK应用。但是,某些用例需要igb_uio或uio_pci_generic驱动程序。

软件轮询模式驱动程序(PMD)


除此之外,DPDK附带的一系列软件PMD不需要通用内核PCI驱动程序,而是依靠标准内核基础架构来提供硬件支持。这样一来,DPDK几乎可以与任何硬件同时使用,即使DPDK本身不支持它。

PCAP库是用于网络硬件的广泛使用和支持的数据包捕获库。目前,DPDK具有可用于PCAP库的PMD。DPDK还支持具有AF_PACKET PMD的Linux网络,而且还可以在DPDK中本地支持AF_XDP。虽然使用这些PMD会有性能成本(有时相当可观的),但其优点是设置很容易,而且这些PMD一般完全不在乎IOVA模式。

总结


本文深入介绍了DPDK如何处理物理内存,也概述了在使用各种Linux *内核驱动程序时DPDK提供的物理寻址功能。

这是关于DPDK内存管理系列文章的第二篇。第一篇文章概述了DPDK内存管理子系统基础的关键原则。本系列接下来的文章将以历史的视角,回顾DPDK长期支持(LTS)版本17.11及更早版本中提供的内存管理功能,同时也会介绍18.11及更高版本DPDK版本中做出的更改和提供的新功能。

推荐阅读


《Linux之hugepage大页内存理论》

《HugeTLB Pages大页内存》

《DPDK如何释放大页内存(巨页内存hugepage)》

《NUMA全称 Non-Uniform Memory Access,译为“非一致性内存访问”,积极NUMA内存策略》

《什么是NUMA?》

《NUMA - Non Uniform Memory Architecture 非统一内存架构》

《《深入浅出DPDK》读书笔记(三):NUMA - Non Uniform Memory Architecture 非统一内存架构》

《Linux内存管理:NUMA技术详解(非一致内存访问架构)》

《直接内存访问 (Direct Memory Access, DMA)》

《搞懂Linux零拷贝,DMA》

《内存管理:Linux Memory Management:MMU、段、分页、PAE、Cache、TLB》

《Linux内存管理:转换后备缓冲区(TLB)原理》

《Linux内存管理:NUMA技术详解(非一致内存访问架构)》

《ARM SMMU原理与IOMMU技术(“VT-d” DMA、I/O虚拟化、内存虚拟化)》

系列文章


《DPDK内存篇(一): 基本概念》

转载须知 :DPDK与SPDK开源社区公众号文章转载声明

DPDK内存篇(二): 深入学习 IOVA相关推荐

  1. DPDK内存篇(三): 标准大页、NUMA、DMA、IOMMU、IOVA、内存池

    作者简介:Anatoly Burakov,英特尔软件工程师,目前在维护DPDK中的VFIO和内存子系统. 目录 引言 标准大页 将内存固定到NUMA节点 硬件.物理地址和直接内存存取(DMA) IOM ...

  2. DPDK内存篇(一): 基本概念

    Table of Contents 引言 标准大页 将内存固定到NUMA节点 硬件.物理地址和直接内存存取(DMA) IOMMU和IOVA 内存分配和管理 结论 推荐阅读 引言 内存管理是数据面开发套 ...

  3. DPDK内存管理二:初始化

    DPDK 内存的初始化主要在rte_eal_init()函数中进行: eal_hugepage_info_init() /* 获取系统中hugepage种类以及数量信息到internal_config ...

  4. DPDK内存(二)内存申请操作

    EAL提供了一个malloc API用于申请任意大小内存. 这个API的目的是提供类似malloc的功能,以允许从hugepage中分配内存并方便应用程序移植. 通常,这些类型的分配操作不应该在数据面 ...

  5. [软考]系统架构设计师 备考经验分享(二) - 知识点学习+综合知识篇

    2021.12.20 更新下成绩 49,53,55 原文: 本篇对应备考计划中的1.2阶段: 相关分享: 备考计划篇:[软考]系统架构设计师 备考经验分享(一) - 备考计划篇 知识点学习+综合知识篇 ...

  6. 帆软FineReport学习篇(二)

    帆软FineReport学习篇(二) 1 制作报表的流程 1.新建数据流程 用于连接数据库 2 新建报表类型 是普通报表还是决策报表 3 新建数据集 从数据库中取出数据 4 报表设计 5 报表预览 查 ...

  7. 计算机系大二学期计划范文,大二学期学习计划范文6篇

    大学二年级是大学生在适应大学生活后,正式进入大学自主学习.生活阶段的初始期.本文是大二学期的学习计划范文,仅供参考. 大二学期学习计划范文一 过去的一学期,是辛苦的但又是充满意义的.不知不觉,已经加入 ...

  8. 计算机系大二学期计划范文,大二学期学习计划范文6篇_大二学生学习计划(2)

    大二学期学习计划范文四 一.前言: 时间如流水般飞逝,转眼之间大二学年的新生活快要开始了.上一学年由于学习任务没有规划好,学习目的不太明确等原因,导致了自己在学习过程中遇到了很多的问题,从而大大降低了 ...

  9. 收藏:DPDK内存基本概念

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 来源:DPDK与SPDK开源社区 作者简介:Anatoly Burakov ...

最新文章

  1. C++ 类构造函数初始化列表介绍
  2. 10 python中的常量
  3. rawquery 没扎到返回什么_当mysql_query返回false时
  4. JAVA中JPasswordField实现密码的确认
  5. 【学习笔记】java基础核心总结
  6. 9008刷机模式写入超时刷机帮_刷机时没有成功,然后变成黑砖,usb接口直接变成未知设备~希望大神救助!...
  7. 关于解决并发问题,99%的程序员都会忽略的一个重要方案!
  8. 之前出的一道背包题面,暂无题解
  9. java中的引用,你注意到没?
  10. vs2008 清理后再编译后卡顿_更新后,竟有这么“严重”的后果?
  11. 常用 Jacobi 行列式 | 重积分变量替换
  12. (23)Java学习笔记——常用对象API / StringBuffer类
  13. maven添加ojdbc6.jar包
  14. chrome控制台出现/null访问
  15. 面试官:“你为什么离开上家公司?”怎么回答?
  16. 1977-1998全国历年高考状元现状
  17. 揭秘强开微粒贷骗局 看完你就明白了
  18. windows 安装labelme
  19. 削华为足,以适IBM之履的再造流程
  20. 关于长尾应用的一些思考

热门文章

  1. 计算机网络 多个站点共享信道的方式图
  2. mysql8.0 利用docker容器安装配置多主多从集群
  3. c++语言中类型的转换
  4. [OpenJudge 3066]随机序列
  5. 我离baidu.com有几跳
  6. 关于OAuth2.0的文章收集
  7. JAVA的Date类与Calendar类
  8. 手动安装cloudera cdh4.2 hadoop + hbase + hive(一)
  9. 寄宿于CS程序的WCF服务
  10. 使用Filter实现用户自动登录