AWS EC2 裸金属实例 DSA 配置指南

概述

DSA (Data Streaming Accelerator) 是 Intel 提供的硬件加速技术,通过卸载 CPU 的数据复制、内存填充、比较等任务来加速数据移动和转换操作。AWS EC2 裸金属实例(如 c7i.metal、c7ie.metal)支持内置的 DSA、IAA(内存分析加速器)和 QuickAssist 等 Intel 加速器,可用于提升以下场景的性能:

  • 高性能网络应用(DPDK 网络栈、OvS-DPDK)
  • 存储密集型应用(NVMe-oF、iSCSI)
  • 内存数据库加速
  • 大数据处理和分析

本将介绍如何在 AWS EC2 裸金属实例上通过 DPDK 使用 DSA,以获得最佳的数据处理性能。

DPDK 使用 DSA 的两种方式

DPDK(Data Plane Development Kit)是业界广泛使用的用户空间高性能数据包处理框架。根据 DPDK 官方文档 IDXD DMA Device Driver,DPDK 应用可以通过以下两种方式使用 DSA:

 Two ways of mapping DSA resources into DPDK applications

方式一:通过 idxd 内核驱动

使用 Linux 内核的 idxd 驱动管理 DSA 设备,内核负责配置工作队列并创建 /dev/dsa/wqX.X 字符设备。DPDK 应用通过标准的文件操作接口提交 DMA 任务。

适用场景:

  • 多个进程共享同一个 DSA 设备
  • 内核态和用户态应用同时使用 DSA

技术要求:

  • Linux 内核 5.11+
  • 硬件/BIOS 支持 SVA(Shared Virtual Addressing)和 PASID

配置示例:

# 使用 accel-config 工具配置工作队列
accel-config config-wq dsa0/wq0.0 --group-id=0 --type=user \
    --wq-size=32 --priority=10 --mode=dedicated
accel-config enable-device dsa0
accel-config enable-wq dsa0/wq0.0

方式二:通过 vfio-pci 用户空间驱动

将 DSA 设备绑定到 vfio-pci 驱动,DPDK 应用在用户空间直接访问设备寄存器,完全控制硬件。DPDK 在应用初始化时自动配置所有工作队列和引擎。

适用场景:

  • DSA 设备专用于单个 DPDK 应用
  • 追求极致性能
  • 硬件/BIOS 不支持 SVA/PASID

技术优势:

  • 性能最优:用户空间直接控制硬件,无系统调用开销
  • 配置简单:DPDK 自动管理所有硬件资源
  • 无 SVA 依赖:不需要 BIOS 启用 SVA/PASID

配置示例:

# 绑定 DSA 设备到 vfio-pci
dpdk-devbind.py -b vfio-pci e7:01.0

EC2 裸金属实例的限制与方案选择

与线下的物理服务器不同,AWS 云上的 EC2 裸金属实例基于 Nitro 系统架构,存在以下技术限制:

限制 1:不支持 SVA/PASID

  • AWS 控制 BIOS 配置,未启用 Shared Virtual Addressing
  • 无法使用 idxd 内核驱动的 user 模式工作队列
  • /dev/dsa/ 设备节点无法生成

限制 2:不支持传统 IOMMU

  • 启用 intel_iommu=on 会与 Nitro 系统冲突,导致实例挂起
  • 传统 vfio-pci 需要 IOMMU 组支持,无法使用

因此,本文将介绍如何使用 vfio-pci no-iommu 模式 + DPDK 在 AWS EC2 裸金属实例上使用 DSA。

配置 DSA 的前置操作

1. 操作系统选择

由于EC2 裸金属实例不支持 SVA/PASID,我们通过 DPDK vfio-pci 驱动使用DSA,目前的主流 Linux 发行版都支持 vfio-pci 驱动:

  • Amazon Linux 2023 (kernel 6.1+)
  • Ubuntu 22.04 LTS (kernel 6.8+)
  • Ubuntu 24.04 LTS
  • RHEL 9+ / CentOS Stream 9+
  • SUSE SLES 15 SP4+

注意:因为使用 vfio-pci 方式,idxd 内核驱动是否可用不影响 DSA 使用。

2. 解决 IOMMU 限制

传统的 vfio-pci 驱动要求设备必须在 IOMMU 组中,以提供 DMA 地址转换和内存保护。IOMMU(Input-Output Memory Management Unit)确保设备只能访问分配给它的内存区域,防止恶意设备访问其他内存。

然而,EC2 裸金属实例基于 Nitro 系统架构,与传统 Intel IOMMU 存在冲突。启用 intel_iommu=on 会导致实例挂起无法启动。

我们可以使用 vfio-pci 的 no-iommu 模式绕过 IOMMU 要求,直接访问硬件。考虑到 c7i.metal 这类裸机实例的特点:

  • 单租户环境,用户完全控制硬件
  • Nitro 系统提供底层硬件隔离
  • 无恶意用户风险

no-iommu 模式在此场景下是安全可用的。

启用 vfio no-iommu 模式:

# 加载 vfio 模块
sudo modprobe vfio

# 启用 no-iommu 模式
sudo sh -c 'echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode'

# 验证已启用
cat /sys/module/vfio/parameters/enable_unsafe_noiommu_mode
# 输出: Y

3. 解决 vfio-pci 设备黑名单限制

Linux 内核 5.9+ 的 vfio-pci 驱动包含设备黑名单,默认禁止 DSA 设备 (8086:0b25) 绑定。这是因为 Intel 加速器(DSA、QAT 等)在设计时未考虑不受信任的用户环境,可能存在可被利用的硬件缺陷。在多租户虚拟化环境中,这些设备不应直接暴露给虚拟机。

但在裸机实例的单租户环境下,用户完全控制硬件,可以安全地禁用黑名单。

当我们直接绑定 DSA 设备时将会收到类似错误信息:

dmesg | grep vfio
# vfio-pci 0000:e7:01.0: 8086:0b25 exists in vfio-pci device denylist, driver probing disallowed.
# vfio-pci: probe of 0000:e7:01.0 failed with error -22

因此,在绑定前我们需要通过一下命令禁用黑名单:

# 1. 卸载 vfio-pci 模块
sudo rmmod vfio_pci
sudo rmmod vfio_pci_core

# 2. 重新加载 vfio-pci 驱动并禁用黑名单
sudo modprobe vfio-pci disable_denylist=Y

# 3. 验证黑名单已禁用
cat /sys/module/vfio_pci/parameters/disable_denylist
# 输出: Y

# 4. 查看可用参数
modinfo vfio-pci | grep denylist
# parm: disable_denylist:Disable use of device denylist. 
#       Disabling the denylist allows binding to devices with known errata 
#       that may lead to exploitable stability or security issues when 
#       accessed by untrusted users. (bool)

永久禁用黑名单(可选):

# 创建模块配置文件
sudo tee /etc/modprobe.d/vfio-pci.conf << EOF
options vfio-pci disable_denylist=Y
EOF

# 更新 initramfs
sudo update-initramfs -u  # Ubuntu/Debian
sudo dracut -f            # RHEL/Amazon Linux

绑定DSA流程

1. 前提条件检查

# 1. 检查 DSA 设备是否可见 (PCI ID: 0x0b25)
lspci -d 8086:0b25

# 预期输出:4 个 DSA 设备
# e7:01.0 System peripheral: Intel Corporation Device 0b25
# ec:01.0 System peripheral: Intel Corporation Device 0b25
# f1:01.0 System peripheral: Intel Corporation Device 0b25
# f6:01.0 System peripheral: Intel Corporation Device 0b25

# 2. 确认 vfio 模块可用
lsmod | grep vfio || sudo modprobe vfio

2. 解绑 idxd 驱动(可选)

如果已加载了 idxd 内核驱动,需要注意设备是否已经在使用 idxd 驱动,需要进行解绑。

# 检查当前驱动
lspci -k -s e7:01.0

# 如果显示 idxd,则需先解绑
sudo sh -c 'echo 0000:e7:01.0 > /sys/bus/pci/drivers/idxd/unbind'

# 或者卸载 idxd 模块(会影响所有设备)
sudo rmmod idxd

3. 绑定到 vfio-pci 驱动

# 1. 设置驱动覆盖
sudo sh -c 'echo vfio-pci > /sys/bus/pci/devices/0000:e7:01.0/driver_override'
# driver_override 告诉内核:这个设备只能绑定到 vfio-pci,忽略其他驱动的匹配规则
# 以防止 idxd 驱动在绑定过程中重新抢占设备

# 2. 绑定设备到 vfio-pci
sudo sh -c 'echo 0000:e7:01.0 > /sys/bus/pci/drivers/vfio-pci/bind'

# 3. 验证绑定成功
lspci -k -s e7:01.0
# 应该显示: Kernel driver in use: vfio-pci

# 4. 检查 VFIO 设备节点
ls -la /dev/vfio/
# 应该看到 /dev/vfio/vfio 和设备节点(如 /dev/vfio/noiommu-0)

# 5. 检查 dmesg
sudo dmesg | grep vfio | tail -5
# 例如: "device denylist disabled - allowing device 8086:0b25"

批量绑定所有 4 个 DSA 设备:

for dev in e7:01.0 ec:01.0 f1:01.0 f6:01.0; do
    sudo sh -c "echo 0000:${dev} > /sys/bus/pci/drivers/idxd/unbind" 2>/dev/null || true
    sudo sh -c "echo vfio-pci > /sys/bus/pci/devices/0000:${dev}/driver_override"
    sudo sh -c "echo 0000:${dev} > /sys/bus/pci/drivers/vfio-pci/bind"
done

# 验证所有设备
lspci -k -d 8086:0b25

4. 使用 DPDK 验证 DSA 可用性

DPDK 安装说明: 如果尚未安装 DPDK,请参考 这篇DPDK安装指导 完成安装。

使用 dpdk-devbind.py 验证:

sudo /path/to/dpdk/usertools/dpdk-devbind.py --status-dev dma

# 期望输出:
# DMA devices using DPDK-compatible driver
# ========================================
# 0000:e7:01.0 'Device 0b25' drv=vfio-pci unused=idxd
# 0000:ec:01.0 'Device 0b25' drv=vfio-pci unused=idxd
# 0000:f1:01.0 'Device 0b25' drv=vfio-pci unused=idxd
# 0000:f6:01.0 'Device 0b25' drv=vfio-pci unused=idxd

注意: dpdk-devbind.py 工具既可以用于绑定设备,也可以用于查看设备状态。在这里我们只用它来验证设备已正确绑定到 vfio-pci(前面步骤已完成绑定)。如果你更喜欢用 dpdk-devbind.py 来绑定设备,可以用 sudo dpdk-devbind.py -b vfio-pci e7:01.0 替代前面的手动绑定步骤。

设置开机自动执行

系统重启后,所有的内核模块参数和设备绑定都会恢复到默认状态:

  • vfio no-iommu 模式会被禁用
  • vfio-pci 黑名单会重新启用
  • DSA 设备会重新绑定到 idxd 驱动(如有启用)

为了避免每次重启后手动配置,我们需要创建 systemd 服务在开机时自动执行配置。

创建 systemd 服务:

sudo tee /etc/systemd/system/dsa-vfio-setup.service << 'EOF'
[Unit]
Description=Setup DSA devices for DPDK vfio-pci
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/dsa-vfio-setup.sh

[Install]
WantedBy=multi-user.target
EOF

创建配置脚本:

sudo tee /usr/local/bin/dsa-vfio-setup.sh << 'EOF'
#!/bin/bash
set -e

# 启用 vfio no-iommu 模式
modprobe vfio
echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode

# 加载 vfio-pci(禁用黑名单)
modprobe vfio-pci disable_denylist=Y

# 绑定所有 DSA 设备
for dev in e7:01.0 ec:01.0 f1:01.0 f6:01.0; do
    echo "0000:${dev}" > /sys/bus/pci/drivers/idxd/unbind 2>/dev/null || true
    echo "vfio-pci" > /sys/bus/pci/devices/0000:${dev}/driver_override
    echo "0000:${dev}" > /sys/bus/pci/drivers/vfio-pci/bind
done

echo "DSA devices bound to vfio-pci successfully"
EOF

sudo chmod +x /usr/local/bin/dsa-vfio-setup.sh

启用服务:

sudo systemctl daemon-reload
sudo systemctl enable dsa-vfio-setup.service
sudo systemctl start dsa-vfio-setup.service

# 检查状态
sudo systemctl status dsa-vfio-setup.service

常见问题及解决方案

1. vfio-pci 模块加载失败

问题描述:

modprobe vfio-pci
# modprobe: ERROR: could not insert 'vfio_pci': Unknown symbol in module

解决步骤:

# 1. 检查模块依赖
lsmod | grep vfio
# 应该看到: vfio_pci, vfio_pci_core, vfio_iommu_type1, vfio

# 2. 按顺序手动加载依赖模块
sudo modprobe vfio
sudo modprobe vfio_iommu_type1
sudo modprobe vfio-pci disable_denylist=Y

# 3. 验证加载成功
lsmod | grep vfio_pci

2. vfio-pci 绑定失败 - Invalid argument

问题描述:

echo 0000:e7:01.0 > /sys/bus/pci/drivers/vfio-pci/bind
# bash: echo: write error: Invalid argument

解决步骤:

# 1. 检查黑名单是否禁用
dmesg | grep "denylist"
# 如果看到 "exists in vfio-pci device denylist" → 需要禁用黑名单

# 2. 检查 no-iommu 模式是否启用
cat /sys/module/vfio/parameters/enable_unsafe_noiommu_mode
# 如果是 N → 需要启用 no-iommu 模式

3. 重启后配置丢失

问题描述:
重启后 DSA 设备恢复使用 idxd 驱动

解决方案:
参考前面的 "永久配置(开机自动生效)" 章节,创建 systemd 服务。

调试命令集合

# 硬件检查
lspci | grep 0b25
lspci -k -d 8086:0b25

# vfio 驱动状态
lsmod | grep vfio
cat /sys/module/vfio_pci/parameters/disable_denylist
cat /sys/module/vfio/parameters/enable_unsafe_noiommu_mode

# 设备绑定状态
ls -la /dev/vfio/

# 系统日志
dmesg | grep vfio | tail -20
dmesg | grep -i dsa

# DPDK 验证
sudo /path/to/dpdk/usertools/dpdk-devbind.py --status-dev dma

参考链接

AWS 官方文档

Intel 官方文档

DPDK 官方文档

Linux 内核文档

Previous Post
No Comment
Add Comment
comment url