Zynq UltraScale+ MPSOC 上的存储性能开发工具套件 (SPDK)
简介
NVMe 存储器件是您系统中的瓶颈吗?也许存储性能开发工具套件(SPDK) 是您通过关注您的 NVMe 存储性能来提高整体系统性能的下一步选择。
SPDK 是一个面向 Linux 用户空间设计的开源项目。SDPK 使用数据平面开发工具套件(DPDK)。SPDK 在成为开源项目之前是 Intel 项目,因此 X86平台是其主要平台。
您对 SDPK 感兴趣可能有两个原因。第一个也是最明显的原因是为了性能。第二个原因可能是需要一个比 Linux 内核许可证更宽松的许可证。
以下段落描述了在赛灵思 ZCU106 电路板上使用的带 MPSOC 的 SPDK 的原型系统。ZCU106 平台是使用 SSD 作为 NVMe PCIe 端点的 PCIe 根联合体。实现基本功能是该原型的唯一目标。
期望
本文档不是针对任何特定元素(如 Linux 或 PetaLinux)设计的教程,而是旨在帮助简化原型制作流程。本文档并不打算一步一步地介绍每个命令,而是想要像实验笔记本描述那样。
测试环境
赛灵思 2019.1 版用于所有使用赛灵思工具的构建。
X86 平台
64 位 X86 PC 用于 SPDK 的早期测试,因为使用与嵌入式平台相同的 NVMe SSD 可以快速验证构建和测试流程。SPDK 文档对于这一早期测试很有用。SPDK 可轻松地在 X86 PC 上进行本地构建,从而加快原型制作流程。
嵌入式平台
赛灵思 ZCU106 电路板被设计成端点,因为它有边缘连接器。对于该原型,ZCU106 电路板与用于 FMC 到 PCIe 主机连接器的 High Tech Global 适配器配合使用。ZCU106 电路板需要使用 PL PCIe 而不是 PS PCIe。带有 PL PCIe 的 ZCU106 用于查看 PCIe 事务(这对于 PS PCIe 更具有挑战性)。

NVMe SSD
Patriot M2 NVMe 128 GB SSD 用于在通用 PCIe x4 到 NVMe M2 承载板中进行测试。
Vivado 系统
ZCU106 的硬件设计采用 XDMA PL PCIe 和硬件一致性生成。在测试的基础上,X86 系统作为硬件一致系统运行,因此 SDPK 不执行高速缓存维护操作。MPSOC 默认为软件一致系统,且必须更改为硬件一致系统才能与 SPDK 一起工作。
XDMA PL PCIe 主端口的 AXI 互连是为基于以下维基页面的硬件一致事务而设置的:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842098/Zynq+UltraScale+MPSoC+Cache+Coherency.
以下摘自 Vivado 原理图的内容说明了添加常量以驱动 axcache 和 axprot 信号以便 PL PCIe 的 AXI 事务具有硬件一致性的方法。

在 Linux 系统中,采用常量 axcache=0b1011 和 axprot=0b010 使读/写事务具有硬件一致性和非安全性。
嵌入式软件
在 Vivado 生成的 HDF 文件的基础上,采用 PetaLinux 为 ZCU106 电路板构建嵌入式 Linux 系统。将设备树机器设置为 zcu106-reva,以便使用该电路板的网络和 SD 卡等功能。

在 PetaLinux rootfs 中关闭了对 GStreamer 和 VCU 包的支持,以减少尺寸并缩短构建时间。作为替代方案,可以使用 Vivado 的 HDF 输出(petalinux-config --get-hw-description)来更新 ZCU106 PetaLinux BSP。
SPDK
最新的 SPDK 源代码来自开源库。

Linux 内核配置和补丁
NVMe 驱动程序
对运行 Linux 内核驱动程序的原型进行早期测试可验证在使用 SPDK 之前NVMe SSD 是否正常工作。NVMe 驱动程序被配置为内置到内核中(CONFIG_NVME_CORE=y, CONFIG_BLK_DEV_NVME=y)。
面向 PCI 的 UIO
UIO PCI 驱动程序被配置为内核模块 (CONFIG_UIO_PCI_GENERIC=m)。SPDK 仅将此驱动程序作为内核模块(而不是内置到内核中)使用。
XDMA PL PCIe
内核被配置为包含 PL PCIe 的驱动程序 (CONFIG_XDMA_PL=y)。
Devmem
在调试期间读/写 DDR 的能力是很好的原型制作工具。由于 SPDK 在 DDR 中使用缓存,关闭 devmem 严格性可允许访问 DDR 以进行调试 (# CONFIG_STRICT_DEVMEM)。
PL PCIe Patch
Linux 内核 2019.1 赛灵思版需要为 PL PCIe 驱动程序提供补丁。参见回答记录 72389 https://www.xilinx.com/support/answers/72389.html 并将补丁应用到内核。
SD 卡准备
分区
SD 卡至少有两个分区。第一个分区是普通赛灵思启动文件的 FAT 分区。第 2 个分区应该是 rootfs 的 Linux 分区。16GB SD 卡将有足够的可用空间。下图显示了 fdisk 实用程序创建的 SD 卡的典型分区集。
使用每个分区的适当 mkfs 实用程序格式化 SD 卡分区。
Petalinux 构建
根文件
自承载包
PetaLinux 包含一个自承载包,它提供了构建 SPDK 所需的大部分工具,如GCC 和 make。在 PetaLinux (petalinux-config -c rootfs) 中启用以下包来构建和调试多线程应用。
附加包
在 PetaLinux (petalinux-config -c rootfs) 中启用 libaio 和 kmod(modinfo实用程序)包,因为它们是构建和执行 SPDK 所必需的。
IMAGE_INSTALL_append = " cunit cunit-dev"
注释: SPDK 中的单元测试需要 cunit 包。作为构建 cunit 包的替代方案,SPDK 可以配置为不使用以下命令行构建测试:
zcu106$ ./configure --disable-tests
从 SD 启动 Rootfs
PetaLinux 默认为 initramfs rootfs,它对较小的 rootfs 很有用。随着 rootfs 变得越来越大,将 rootfs 放在SD卡上就变得更具挑战性。
更改 PetaLinux 顶级配置 (petalinux-config) 以从 SD 卡上所需的 Linux 分区启动。下图显示了使用 rootfs 的第 3 个分区:

将 Rootfs 复制到 SD
PetaLinux 为 SD 卡提供多个 rootfs 镜像。将 rootfs.tar.bz 用于原型,如下所示:
$ sudo tar xvjf rootfs.tar.bz2 -C
$ sync
一致性软件安装
硬件一致性要求硬件和软件都要进行更改。以下维基页面的“早期启动时的寄存器写入”部分用于设置软件中的一致性:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842098/Zynq+UltraScale+MPSoC+Cache+Coherency.
BIF 文件更改
在为普通boot.BIN 生成执行 PetaLinux 包 (petalinux-package --boot) 命令后,项目的构建目录中会存在 bootgen.bif 文件。Bootgen 使用 BIF 文件创建 BOOT.BIN。
将 bootgen.bif 从构建目录复制到 PetaLinux 项目的 images/linux 目录中。编辑文件,删除文件路径,以便它使用 images/linux 目录中的文件。将“[init]regs.init”行添加到文件中,如下面示例所示:
the_ROM_image:
{
[init] regs.init
[bootloader, destination_cpu=a53-0] zynqmp_fsbl.elf
[pmufw_image] pmufw.elf
[destination_device=pl] design_1_wrapper-coherent.bit
[destination_cpu=a53-0, exception_level=el-3, trustzone] bl31.elf
[destination_cpu=a53-0, exception_level=el-2] u-boot.elf
}
寄存器初始化
在上一步中创建的 BIF 文件引用名为 regs.init 的文件,该文件支持早期寄存器初始化。在 PetaLinux 项目的 images/linux 目录中创建此文件,内容如下。
.set. 0xFF41A040 = 0x3;
设置 LPD_SLCR 寄存器的广播内部位将开启内部共享事务从内部域到外部域的广播,并启用硬件一致性。
有关此寄存器初始化的详细信息在引用的维基页面上进行了描述。
BOOT.BIN 生成
PetaLinux 用于使用新的 bif 文件生成 BOOT.BIN,下面的命令假设它从PetaLinux 项目的 images/linux 目录执行。
host$ petalinux-package --boot --bif bootgen.bif --force
ZCU106上的 SPDK
此步骤用于下载、构建(本地)并在 ZCU106 上运行 SPDK。ZCU106 的网络应功能正常,且需要执行以下步骤。文档和详细信息请参见位于 https://spdk.io/ 的 SPDK。
下载源代码
DPDK
DPDK 必须配置为在没有 NUMA 支持的情况下构建,因为 MPSOC 不是NUMA 架构。将 DPDK 从一个嵌套目录中的 SPDK 复制到另一个非嵌套目录中,以便在 SPDK 之外构建。这样做是因为它似乎是为 MPSOC 配置 DPDK 的最简单方法。
zu106$ cp -Rd spdk/dpdk dpdk
zu106$ cd dpdk
zu106$ edit config/defconfig_arm64-armv8a-linuxapp-gcc adding the following lines.
CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=n
CONFIG_RTE_LIBRTE_VHOST_NUMA=n
zu106$ make config T=arm64-armv8a-linuxapp-gcc
zu106$ make -j 4
SPDK 构建
配置 SPDK 以使用在 SPDK 之外构建的DPDK。然后构建 SPDK。
zu106$ ./configure --with-dpdk=
zu106$ make -j 4
SPDK 初始化
初始化 SPDK 以解除 NVMe 驱动程序的绑定并绑定 uio_pci_generic 内核模块。
zu106$ su
zu106$ ./scripts/setup.sh

运行 Hello World
运行 hello world 示例,得到如下所示的典型结果。
zcu106$ ./examples/nvme/hello_world/hello_world

原型挑战
带有 MPSOC 的第一个硬件原型具有软件一致性,它不适用于 SPDK。Hello world 示例只会超时而不起作用。
通过使用 GDB 逐步执行 hello world 示例可以触摸到数据缓存,以便从高速缓存中刷新它们,并且可以在响应缓存中看到响应。
软件相干系统的 PCIe 事务也使用 ILA 汇集。NVMe 目标从主机存储器读取以从命令队列获取命令。PCIe 事务验证得出 NVMe 目标在从 ZCU106 存储器读取 Identify 命令时得到的全部为零。
性能基线
不需要构建系统来提高性能。以下性能数值仅作为基线。
root@zcu106-ubuntu:/home/xilinx/spdk/examples/nvme/perf# lspci
00:00.0 PCI bridge: Xilinx Corporation Device 9118
01:00.0 Non-Volatile memory controller: Device 1987:5008 (rev 01)
root@zcu106-plpcie-106:~/spdk/examples/nvme/perf# ./perf -q 128 -o 4096 -w randread -r 'trtype:PCIe traddr 0000:01:00.0' -t 300
nvme.c: 884:spdk_nvme_transport_id_parse: *ERROR*: Unknown transport ID key 'traddr 0000'
Starting SPDK v19.07-pre / DPDK 19.05.0 initialization...
[ DPDK EAL parameters: perf --no-shconf -c 0x1 --log-level=lib.eal:6 --log-level=lib.cryptodev:5 --log-level=user1:6 --base-virtaddr=0x200000000000 --match-allocations --file-prefix=spdk_pid2879 ]
Initializing NVMe Controllers
Attaching to NVMe Controller at 0000:01:00.0
Attached to NVMe Controller at 0000:01:00.0 [1987:5008]
Associating PCIE (0000:01:00.0) with lcore 0
Initialization complete. Launching workers.
Starting thread on core 0
========================================================
Latency(us)
Device Information : IOPS MiB/s Average min max
PCIE (0000:01:00.0) from core 0: 100062.53 390.87 1279.13 703.37 12005575.48
========================================================
Total : 100062.53 390.87 1279.13 703.37 12005575.48
结论
SPDK 系统原型的构建和测试只需进行前面几段所示的少量工作。硬件一致系统是为原型制作提供支持所需的唯一硬件更改。使用 PetaLinux 支持的自承载系统可以轻松构建原型软件。位于 https://spdk.io/doc/getting_started.html 的 SPDK 文档提供了原型制作所需的所有细节。
通过少量的原型制作工作,SPDK 可以作为一个系统解决方案进行评估,从而有望通过基于 NVMe 的存储来提高系统的整体性能。