FPGA 设备功能列表 (DFL) 框架概述

作者

设备功能列表 (DFL) FPGA 框架(以及根据此框架的驱动程序)隐藏了底层硬件的细节,并为用户空间提供了统一的接口。应用程序可以使用这些接口来配置、枚举、打开和访问在设备内存中实现 DFL 的平台上的 FPGA 加速器。此外,DFL 框架还支持系统级管理功能,例如 FPGA 重配置。

设备功能列表 (DFL) 概述

设备功能列表 (DFL) 在设备 MMIO 空间内定义了一个功能头部的链表,以提供一种可扩展的方式来添加功能。软件可以遍历这些预定义的数据结构来枚举 FPGA 功能:FPGA 接口单元 (FIU)、加速功能单元 (AFU) 和私有功能,如下所示

   Header            Header            Header            Header
+----------+  +-->+----------+  +-->+----------+  +-->+----------+
|   Type   |  |   |  Type    |  |   |  Type    |  |   |  Type    |
|   FIU    |  |   | Private  |  |   | Private  |  |   | Private  |
+----------+  |   | Feature  |  |   | Feature  |  |   | Feature  |
| Next_DFH |--+   +----------+  |   +----------+  |   +----------+
+----------+      | Next_DFH |--+   | Next_DFH |--+   | Next_DFH |--> NULL
|    ID    |      +----------+      +----------+      +----------+
+----------+      |    ID    |      |    ID    |      |    ID    |
| Next_AFU |--+   +----------+      +----------+      +----------+
+----------+  |   | Feature  |      | Feature  |      | Feature  |
|  Header  |  |   | Register |      | Register |      | Register |
| Register |  |   |   Set    |      |   Set    |      |   Set    |
|   Set    |  |   +----------+      +----------+      +----------+
+----------+  |      Header
              +-->+----------+
                  |   Type   |
                  |   AFU    |
                  +----------+
                  | Next_DFH |--> NULL
                  +----------+
                  |   GUID   |
                  +----------+
                  |  Header  |
                  | Register |
                  |   Set    |
                  +----------+

FPGA 接口单元 (FIU) 表示用于 FPGA 接口的独立功能单元,例如 FPGA 管理引擎 (FME) 和端口(有关 FME 和端口的更多描述将在后续章节中介绍)。

加速功能单元 (AFU) 表示 FPGA 可编程区域,并且始终作为其子项连接到 FIU(例如端口),如上图所示。

私有功能表示 FIU 和 AFU 的子功能。它们可能是具有不同 ID 的各种功能块,但属于同一 FIU 或 AFU 的所有私有功能必须通过下一个设备功能头 (Next_DFH) 指针链接到一个列表中。

每个 FIU、AFU 和私有功能都可以实现自己的功能寄存器。FIU 和 AFU 的功能寄存器集称为头寄存器集,例如 FME 头寄存器集,而私有功能的功能寄存器集称为功能寄存器集,例如 FME 部分重配置功能寄存器集。

此设备功能列表提供了一种将功能链接在一起的方法,方便软件通过遍历此列表来定位每个功能,并且可以在任何 FPGA 设备的寄存器区域中实现。

设备功能头 - 版本 0

版本 0 (DFHv0) 是设备功能头的原始版本。DFHv0 中的所有多字节数量均为小端字节序。DFHv0 的格式如下所示

+-----------------------------------------------------------------------+
|63 Type 60|59 DFH VER 52|51 Rsvd 41|40 EOL|39 Next 16|15 REV 12|11 ID 0| 0x00
+-----------------------------------------------------------------------+
|63                                 GUID_L                             0| 0x08
+-----------------------------------------------------------------------+
|63                                 GUID_H                             0| 0x10
+-----------------------------------------------------------------------+
  • 偏移量 0x00

    • 类型 - DFH 的类型(例如 FME、AFU 或私有功能)。

    • DFH VER - DFH 的版本。

    • Rsvd - 当前未使用。

    • EOL - 如果 DFH 是设备功能列表 (DFL) 的末尾,则设置。

    • 下一个 - 从 DFH 开始的 DFL 中下一个 DFH 的字节偏移量,DFH 的开始必须与 8 字节边界对齐。如果设置了 EOL,则 Next 是列表中最后一个功能的 MMIO 大小。

    • REV - 与此标头关联的功能的修订版。

    • ID - 如果类型为私有功能,则为功能 ID。

  • 偏移量 0x08

    • GUID_L - 128 位全局唯一标识符的最低有效 64 位(仅当类型为 FME 或 AFU 时存在)。

  • 偏移量 0x10

    • GUID_H - 128 位全局唯一标识符的最高有效 64 位(仅当类型为 FME 或 AFU 时存在)。

设备功能头 - 版本 1

设备功能头的版本 1 (DFHv1) 添加了以下功能

  • 为功能提供了一种标准化的机制,用于向软件描述参数/功能。

  • 标准化所有 DFHv1 类型使用 GUID。

  • 将 DFH 位置与功能本身的寄存器空间分离。

DFHv1 中的所有多字节数量均为小端字节序。版本 1 的设备功能头 (DFH) 的格式如下所示

+-----------------------------------------------------------------------+
|63 Type 60|59 DFH VER 52|51 Rsvd 41|40 EOL|39 Next 16|15 REV 12|11 ID 0| 0x00
+-----------------------------------------------------------------------+
|63                                 GUID_L                             0| 0x08
+-----------------------------------------------------------------------+
|63                                 GUID_H                             0| 0x10
+-----------------------------------------------------------------------+
|63                   Reg Address/Offset                      1|  Rel  0| 0x18
+-----------------------------------------------------------------------+
|63        Reg Size       32|Params 31|30 Group    16|15 Instance      0| 0x20
+-----------------------------------------------------------------------+
|63 Next    35|34RSV33|EOP32|31 Param Version 16|15 Param ID           0| 0x28
+-----------------------------------------------------------------------+
|63                 Parameter Data                                     0| 0x30
+-----------------------------------------------------------------------+

                              ...

+-----------------------------------------------------------------------+
|63 Next    35|34RSV33|EOP32|31 Param Version 16|15 Param ID           0|
+-----------------------------------------------------------------------+
|63                 Parameter Data                                     0|
+-----------------------------------------------------------------------+
  • 偏移量 0x00

    • 类型 - DFH 的类型(例如 FME、AFU 或私有功能)。

    • DFH VER - DFH 的版本。

    • Rsvd - 当前未使用。

    • EOL - 如果 DFH 是设备功能列表 (DFL) 的末尾,则设置。

    • 下一个 - 从 DFH 开始的 DFL 中下一个 DFH 的字节偏移量,DFH 的开始必须与 8 字节边界对齐。如果设置了 EOL,则 Next 是列表中最后一个功能的 MMIO 大小。

    • REV - 与此标头关联的功能的修订版。

    • ID - 如果类型为私有功能,则为功能 ID。

  • 偏移量 0x08

    • GUID_L - 128 位全局唯一标识符的最低有效 64 位。

  • 偏移量 0x10

    • GUID_H - 128 位全局唯一标识符的最高有效 64 位。

  • 偏移量 0x18

    • 寄存器地址/偏移量 - 如果设置了 Rel 位,则该值是功能寄存器的 16 位对齐绝对地址的高 63 位。否则,该值是从功能寄存器的 DFH 开头的偏移量。

  • 偏移量 0x20

    • 寄存器大小 - 功能寄存器集的大小(以字节为单位)。

    • 参数 - 如果 DFH 有参数块列表,则设置。

    • 组 - 如果功能是组的一部分,则为组的 ID。

    • 实例 - 组内功能实例的 ID。

  • 如果功能有参数,则为偏移量 0x28

    • 下一个 - 下一个参数块的偏移量(以 8 字节字为单位)。如果设置了 EOP,则为最后一个参数的大小(以 8 字节字为单位)。

    • 参数版本 - 参数 ID 的版本。

    • 参数 ID - 参数的 ID。

  • 偏移量 0x30

    • 参数数据 - 参数数据,其大小和格式由参数的版本和 ID 定义。

FIU - FME(FPGA 管理引擎)

FPGA 管理引擎执行重配置和其他基础结构功能。每个 FPGA 设备只有一个 FME。

用户空间应用程序可以使用 open() 获取对 FME 的独占访问权限,并使用 close() 释放它。

以下功能通过 ioctl 公开

  • 获取驱动程序 API 版本 (DFL_FPGA_GET_API_VERSION)

  • 检查扩展 (DFL_FPGA_CHECK_EXTENSION)

  • 编程比特流 (DFL_FPGA_FME_PORT_PR)

  • 将端口分配给 PF (DFL_FPGA_FME_PORT_ASSIGN)

  • 从 PF 释放端口 (DFL_FPGA_FME_PORT_RELEASE)

  • 获取 FME 全局错误的 irq 数 (DFL_FPGA_FME_ERR_GET_IRQ_NUM)

  • 为 FME 错误设置中断触发 (DFL_FPGA_FME_ERR_SET_IRQ)

更多功能通过 sysfs (/sys/class/fpga_region/regionX/dfl-fme.n/) 公开

读取比特流 ID (bitstream_id)

bitstream_id 指示静态 FPGA 区域的版本。

读取比特流元数据 (bitstream_metadata)

bitstream_metadata 包括静态 FPGA 区域的详细信息,例如综合日期和种子。

读取端口数 (ports_num)

一个 FPGA 设备可能有一个以上的端口,此 sysfs 接口指示 FPGA 设备有多少个端口。

全局错误报告管理 (errors/)

错误报告 sysfs 接口允许用户读取硬件检测到的错误,并清除已记录的错误。

电源管理 (dfl_fme_power hwmon)

电源管理 hwmon sysfs 接口允许用户读取电源管理信息(功耗、阈值、阈值状态、限制等)并配置不同节流级别的电源阈值。

散热管理 (dfl_fme_thermal hwmon)

散热管理 hwmon sysfs 接口允许用户读取散热管理信息(当前温度、阈值、阈值状态等)。

性能报告

性能计数器通过 perf PMU API 公开。可以使用标准的 perf 工具来监视所有可用的 perf 事件。有关更多详细信息,请参见下面的性能计数器部分。

FIU - 端口

端口表示静态 FPGA 结构与包含 AFU 的部分可重配置区域之间的接口。它控制从软件到加速器的通信,并公开诸如重置和调试之类的功能。每个 FPGA 设备可能有一个以上的端口,但每个端口始终只有一个 AFU。

AFU

AFU 连接到端口 FIU,并公开一个固定长度的 MMIO 区域,用于加速器特定的控制寄存器。

用户空间应用程序可以通过在端口设备节点上使用 open() 获取对连接到端口的 AFU 的独占访问权限,并使用 close() 释放它。

以下功能通过 ioctl 公开

  • 获取驱动程序 API 版本 (DFL_FPGA_GET_API_VERSION)

  • 检查扩展 (DFL_FPGA_CHECK_EXTENSION)

  • 获取端口信息 (DFL_FPGA_PORT_GET_INFO)

  • 获取 MMIO 区域信息 (DFL_FPGA_PORT_GET_REGION_INFO)

  • 映射 DMA 缓冲区 (DFL_FPGA_PORT_DMA_MAP)

  • 取消映射 DMA 缓冲区 (DFL_FPGA_PORT_DMA_UNMAP)

  • 重置 AFU (DFL_FPGA_PORT_RESET)

  • 获取端口错误的 irq 数 (DFL_FPGA_PORT_ERR_GET_IRQ_NUM)

  • 为端口错误设置中断触发 (DFL_FPGA_PORT_ERR_SET_IRQ)

  • 获取 UINT 的 irq 数 (DFL_FPGA_PORT_UINT_GET_IRQ_NUM)

  • 为 UINT 设置中断触发 (DFL_FPGA_PORT_UINT_SET_IRQ)

DFL_FPGA_PORT_RESET

重置 FPGA 端口及其 AFU。用户空间可以随时进行端口重置,例如在 DMA 或部分重配置期间。但这绝不应导致任何系统级问题,只会导致功能故障(例如 DMA 或 PR 操作失败),并且可以从故障中恢复。

用户空间应用程序还可以 mmap() 加速器 MMIO 区域。

更多功能通过 sysfs 公开:(/sys/class/fpga_region/<regionX>/<dfl-port.m>/)

读取加速器 GUID (afu_id)

afu_id 指示将哪个 PR 比特流编程到此 AFU。

错误报告 (errors/)

错误报告 sysfs 接口允许用户读取硬件检测到的端口/afu 错误,并清除已记录的错误。

DFL 框架概述

       +----------+    +--------+ +--------+ +--------+
       |   FME    |    |  AFU   | |  AFU   | |  AFU   |
       |  Module  |    | Module | | Module | | Module |
       +----------+    +--------+ +--------+ +--------+
               +-----------------------+
               | FPGA Container Device |    Device Feature List
               |  (FPGA Base Region)   |         Framework
               +-----------------------+
------------------------------------------------------------------
             +----------------------------+
             |   FPGA DFL Device Module   |
             | (e.g. PCIE/Platform Device)|
             +----------------------------+
               +------------------------+
               |  FPGA Hardware Device  |
               +------------------------+

内核中的 DFL 框架提供了通用接口,用于创建容器设备(FPGA 基区域),从给定的设备特性列表发现特性设备及其私有特性,并为特性设备(例如 FME、端口和 AFU)创建平台设备,这些平台设备在容器设备下具有相关资源。它还抽象了私有特性的操作,并向特性设备驱动程序公开通用操作。

FPGA DFL 设备可能是不同的硬件,例如 PCIe 设备、平台设备等。一旦系统创建该设备,其驱动程序模块总是首先被加载。该驱动程序在驱动程序架构中起着基础设施的作用。它在设备内存中定位 DFL,处理它们以及相关资源,并将其传递给 DFL 框架中的通用接口以进行枚举。(有关详细的枚举 API,请参阅 drivers/fpga/dfl.c)。

FPGA 管理引擎 (FME) 驱动程序是一个平台驱动程序,在 DFL 设备模块创建 FME 平台设备后自动加载。它为 FPGA 管理提供关键功能,包括

  1. 公开静态 FPGA 区域信息,例如版本和元数据。用户可以通过 FME 驱动程序公开的 sysfs 接口读取相关信息。

  2. 部分重配置。FME 驱动程序在 PR 子特性初始化期间创建 FPGA 管理器、FPGA 桥接器和 FPGA 区域。一旦它收到来自用户的 DFL_FPGA_FME_PORT_PR ioctl,它将调用 FPGA 区域中的通用接口函数,以完成将 PR 比特流部分重配置到给定端口的操作。

与 FME 驱动程序类似,FPGA 加速功能单元 (AFU) 驱动程序在创建 AFU 平台设备后会被探测到。该模块的主要功能是为用户空间应用程序提供访问单个加速器的接口,包括端口上的基本复位控制、AFU MMIO 区域导出、DMA 缓冲区映射服务函数。

在创建特性平台设备后,匹配的平台驱动程序将自动加载以处理不同的功能。有关已在此 DFL 框架下实现的详细功能单元信息,请参阅下一节。

部分重配置

如上所述,可以通过对 PR 比特流文件进行部分重配置来重新配置加速器。PR 比特流文件必须是为 FPGA 的精确静态 FPGA 区域和目标可重配置区域(端口)生成的,否则,重配置操作将失败,并可能导致系统不稳定。可以通过将 PR 比特流文件头中记录的兼容性 ID 与目标 FPGA 区域公开的 compat_id 进行比较来检查此兼容性。此检查通常在调用重配置 IOCTL 之前由用户空间完成。

FPGA 虚拟化 - PCIe SRIOV

本节介绍基于 DFL 的 FPGA 设备上的虚拟化支持,以允许从虚拟机 (VM) 中运行的应用程序访问加速器。本节仅介绍支持 SRIOV 的基于 PCIe 的 FPGA 设备。

特定 FPGA 设备支持的功能通过设备特性列表公开,如下所示

  +-------------------------------+  +-------------+
  |              PF               |  |     VF      |
  +-------------------------------+  +-------------+
      ^            ^         ^              ^
      |            |         |              |
+-----|------------|---------|--------------|-------+
|     |            |         |              |       |
|  +-----+     +-------+ +-------+      +-------+   |
|  | FME |     | Port0 | | Port1 |      | Port2 |   |
|  +-----+     +-------+ +-------+      +-------+   |
|                  ^         ^              ^       |
|                  |         |              |       |
|              +-------+ +------+       +-------+   |
|              |  AFU  | |  AFU |       |  AFU  |   |
|              +-------+ +------+       +-------+   |
|                                                   |
|            DFL based FPGA PCIe Device             |
+---------------------------------------------------+

FME 始终通过物理功能 (PF) 访问。

端口(和相关的 AFU)默认情况下通过 PF 访问,但可以通过 PCIe SRIOV 通过虚拟功能 (VF) 设备公开。每个 VF 仅包含 1 个端口和 1 个 AFU 用于隔离。用户可以将通过 PCIe SRIOV 接口创建的单个 VF(加速器)分配给虚拟机。

虚拟化情况下的驱动程序组织如下所示

 +-------++------++------+             |
 | FME   || FME  || FME  |             |
 | FPGA  || FPGA || FPGA |             |
 |Manager||Bridge||Region|             |
 +-------++------++------+             |
 +-----------------------+  +--------+ |             +--------+
 |          FME          |  |  AFU   | |             |  AFU   |
 |         Module        |  | Module | |             | Module |
 +-----------------------+  +--------+ |             +--------+
       +-----------------------+       |       +-----------------------+
       | FPGA Container Device |       |       | FPGA Container Device |
       |  (FPGA Base Region)   |       |       |  (FPGA Base Region)   |
       +-----------------------+       |       +-----------------------+
         +------------------+          |         +------------------+
         | FPGA PCIE Module |          | Virtual | FPGA PCIE Module |
         +------------------+   Host   | Machine +------------------+
-------------------------------------- | ------------------------------
          +---------------+            |          +---------------+
          | PCI PF Device |            |          | PCI VF Device |
          +---------------+            |          +---------------+

一旦检测到 FPGA PCIe PF 或 VF 设备,FPGA PCIe 设备驱动程序始终首先加载。它

  • 使用 DFL 框架的通用接口完成对 FPGA PCIe PF 和 VF 设备的枚举。

  • 支持 SRIOV。

FME 设备驱动程序在此驱动程序架构中起着管理作用,它提供 ioctl 来从 PF 释放端口并将端口分配给 PF。从 PF 释放端口后,就可以通过 PCIe SRIOV sysfs 接口安全地通过 VF 公开此端口。

要允许从虚拟机中运行的应用程序访问加速器,需要使用以下步骤将相应 AFU 的端口分配给 VF

  1. PF 默认拥有所有 AFU 端口。任何需要重新分配给 VF 的端口必须首先通过 FME 设备上的 DFL_FPGA_FME_PORT_RELEASE ioctl 释放。

  2. 一旦从 PF 释放 N 个端口,则用户可以使用以下命令启用 SRIOV 和 VF。每个 VF 仅拥有一个带有 AFU 的端口。

    echo N > $PCI_DEVICE_PATH/sriov_numvfs
    
  3. 将 VF 传递到虚拟机

  4. VF 下的 AFU 可以从虚拟机中的应用程序访问(使用 VF 内部的相同驱动程序)。

请注意,FME 不能分配给 VF,因此 PR 和其他管理功能仅通过 PF 可用。

设备枚举

本节介绍应用程序如何从 /sys/class/fpga_region 下的 sysfs 层次结构枚举 fpga 设备。

在下面的示例中,主机中安装了两个基于 DFL 的 FPGA 设备。每个 fpga 设备都有一个 FME 和两个端口(AFU)。

FPGA 区域在 /sys/class/fpga_region/ 下创建

/sys/class/fpga_region/region0
/sys/class/fpga_region/region1
/sys/class/fpga_region/region2
...

应用程序需要搜索每个 regionX 文件夹,如果找到特性设备(例如,找到“dfl-port.n”或“dfl-fme.m”),则它是表示 FPGA 设备的基 fpga 区域。

每个基本区域都有一个 FME 和两个端口 (AFU) 作为子设备

/sys/class/fpga_region/region0/dfl-fme.0
/sys/class/fpga_region/region0/dfl-port.0
/sys/class/fpga_region/region0/dfl-port.1
...

/sys/class/fpga_region/region3/dfl-fme.1
/sys/class/fpga_region/region3/dfl-port.2
/sys/class/fpga_region/region3/dfl-port.3
...

一般来说,FME/AFU sysfs 接口的命名如下

/sys/class/fpga_region/<regionX>/<dfl-fme.n>/
/sys/class/fpga_region/<regionX>/<dfl-port.m>/

其中 “n” 连续编号所有 FME,“m” 连续编号所有端口。

用于 ioctl() 或 mmap() 的设备节点可以通过以下方式引用

/sys/class/fpga_region/<regionX>/<dfl-fme.n>/dev
/sys/class/fpga_region/<regionX>/<dfl-port.n>/dev

性能计数器

性能报告是 FME 中实现的一项私有特性。它可以在硬件中支持多个独立的、系统范围的设备计数器集,以监视和计数性能事件,包括“basic”、“cache”、“fabric”、“vtd” 和 “vtd_sip” 计数器。用户可以使用标准的 perf 工具来监视 FPGA 缓存命中/未命中率、事务数量、AFU 的接口时钟计数器和其他 FPGA 性能事件。

不同的 FPGA 设备可能有不同的计数器集,具体取决于硬件实现。例如,一些独立的 FPGA 卡没有任何缓存。用户可以使用 “perf list” 来检查目标硬件支持哪些 perf 事件。

为了允许用户使用标准的 perf API 来访问这些性能计数器,驱动程序会创建一个 perf PMU 以及 /sys/bus/event_source/devices/dfl_fme* 中的相关 sysfs 接口来描述可用的 perf 事件和配置选项。

“format” 目录描述了 struct perf_event_attr 的 config 字段的格式。config 有 3 个位域:“evtype” 定义 perf 事件所属的类型;“event” 是其类别中事件的标识;引入 “portid” 来决定要监视 FPGA 整体数据还是特定端口的计数器集。

“events” 目录描述了所有可用事件的配置模板,这些模板可以直接与 perf 工具一起使用。例如,fab_mmio_read 的配置为 “event=0x06,evtype=0x02,portid=0xff”,这表明此事件属于 fabric 类型 (0x02),本地事件 id 为 0x06,并且用于整体监视 (portid=0xff)。

perf 的示例用法

$# perf list |grep dfl_fme

dfl_fme0/fab_mmio_read/                              [Kernel PMU event]
<...>
dfl_fme0/fab_port_mmio_read,portid=?/                [Kernel PMU event]
<...>

$# perf stat -a -e dfl_fme0/fab_mmio_read/ <command>
or
$# perf stat -a -e dfl_fme0/event=0x06,evtype=0x02,portid=0xff/ <command>
or
$# perf stat -a -e dfl_fme0/config=0xff2006/ <command>

另一个示例,fab_port_mmio_read 监视特定端口的 mmio 读取。因此,其配置模板为 “event=0x06,evtype=0x01,portid=?”。应显式设置 portid。

它对 perf 的使用

$# perf stat -a -e dfl_fme0/fab_port_mmio_read,portid=0x0/ <command>
or
$# perf stat -a -e dfl_fme0/event=0x06,evtype=0x02,portid=0x0/ <command>
or
$# perf stat -a -e dfl_fme0/config=0x2006/ <command>

请注意,对于 fabric 计数器,整体 perf 事件 (fab_*) 和端口 perf 事件 (fab_port_*) 实际上共享硬件中的一组计数器,因此它们不能同时监视两者。如果此计数器集配置为监视整体数据,则不支持每个端口的 perf 数据。请参见以下示例

$# perf stat -e dfl_fme0/fab_mmio_read/,dfl_fme0/fab_port_mmio_write,\
                                                  portid=0/ sleep 1

Performance counter stats for 'system wide':

               3      dfl_fme0/fab_mmio_read/
 <not supported>      dfl_fme0/fab_port_mmio_write,portid=0x0/

     1.001750904 seconds time elapsed

驱动程序还提供一个 “cpumask” sysfs 属性,其中仅包含一个用于访问这些 perf 事件的 CPU id。不允许在多个 CPU 上进行计数,因为它们是 FPGA 设备上的系统范围计数器。

当前驱动程序不支持采样。因此不支持 “perf record”。

中断支持

一些 FME 和 AFU 私有特性能够生成中断。如上所述,用户可以调用 ioctl (DFL_FPGA_*_GET_IRQ_NUM) 来了解此私有特性支持多少中断或是否支持中断。驱动程序还为用户实现了一个基于 eventfd 的中断处理机制,以便在发生中断时获得通知。用户可以通过 ioctl (DFL_FPGA_*_SET_IRQ) 将 eventfd 设置到驱动程序,然后轮询/选择这些 eventfd 以等待通知。在当前 DFL 中,3 个子特性(端口错误、FME 全局错误和 AFU 中断)支持中断。

添加新的 FIU 支持

在此 DFL 框架下,开发人员可能会创建一些新的功能块 (FIU),然后需要为新特性设备 (FIU) 开发新的平台设备驱动程序,其方式与现有特性设备驱动程序(例如,FME 和端口/AFU 平台设备驱动程序)相同。除此之外,还需要修改 DFL 框架枚举代码,以便进行新的 FIU 类型检测和创建相关的平台设备。

添加新的私有特性支持

在某些情况下,我们可能需要在现有 FIU(例如 FME 或端口)中添加一些新的私有特性。开发人员不需要触及 DFL 框架中的枚举代码,因为每个私有特性都将自动解析,并且可以在 DFL 框架创建的 FIU 平台设备下找到相关的 mmio 资源。开发人员只需要提供一个具有匹配特性 id 的子特性驱动程序。FME 部分重配置子特性驱动程序(请参阅 drivers/fpga/dfl-fme-pr.c)可以作为参考。

请参阅以下链接,了解现有的特性 id 表和新特性 id 应用程序的指南。https://github.com/OPAE/dfl-feature-id

PCI 设备上 DFL 的位置

最初在 PCI 设备上查找 DFL 的方法假设第一个 DFL 的起始位置是 bar 0 的偏移量 0。如果 DFL 的第一个节点是 FME,则端口中的其他 DFL 在 FME 头部寄存器中指定。或者,可以使用 PCIe 供应商特定的能力结构来指定设备上所有 DFL 的位置,从而为 DFL 中起始节点的类型提供灵活性。英特尔为此目的保留了 VSEC ID 0x43。供应商特定数据以一个 4 字节的供应商特定寄存器开始,用于表示 DFL 的数量,然后是每个 DFL 的 4 字节偏移量/BIR 供应商特定寄存器。偏移量/BIR 寄存器的位 2:0 表示 BAR,位 31:3 表示 8 字节对齐的偏移量,其中位 2:0 为零。

+----------------------------+
|31     Number of DFLS      0|
+----------------------------+
|31     Offset     3|2 BIR  0|
+----------------------------+
              . . .
+----------------------------+
|31     Offset     3|2 BIR  0|
+----------------------------+

已经考虑过为每个 BAR 指定多个 DFL 的可能性,但确定该用例没有提供价值。为每个 BAR 指定单个 DFL 可以简化实现并允许额外的错误检查。

DFL 设备的用户空间驱动程序支持

FPGA 的目的是使用新开发的硬件组件进行重新编程。新的硬件可以在 DFL 中实例化一个新的私有特性,然后在系统中呈现一个 DFL 设备。在某些情况下,用户可能需要 DFL 设备的用户空间驱动程序。

  • 用户可能需要为其硬件运行一些诊断测试。

  • 用户可以在用户空间中原型化内核驱动程序。

  • 一些硬件是为特定目的而设计的,不适合标准的内核子系统。

这需要直接访问 MMIO 空间和来自用户空间的 interrupts 处理。uio_dfl 模块为此目的公开了 UIO 设备接口。

目前,uio_dfl 驱动程序仅支持 Ether Group 子功能,该功能在硬件中没有 irq。因此,此驱动程序中未添加中断处理。

应选择 UIO_DFL 以启用 uio_dfl 模块驱动程序。要通过 UIO 直接访问支持新的 DFL 功能,应将其功能 ID 添加到驱动程序的 id_table 中。

公开讨论

FME 驱动程序现在为用户导出一个 ioctl (DFL_FPGA_FME_PORT_PR) 用于部分重新配置。将来,如果添加了统一的重新配置用户界面,FME 驱动程序应从 ioctl 接口切换到它们。