PCIe 中的 ARI 介绍
1、PCIe 配置空间回顾
- PCI 3.0 Compatible Configuration Space:64 字节是标准配置空间 header,兼容 PCI 3.0
- PCI Express Capability Structure:标准 PCI 配置空间(前 256 字节)中的一项能力结构,用来描述设备是否支持 PCI Express 及其基本特性。例如:Link Capabilities(链路能力,如带宽、速率)、Device Capabilities(设备能力)、Link Status(链路状态)等
- PCI Express Extended Configuration Space:PCI Express 为每个功能块(Function)定义了比传统 PCI 更大的配置空间,容纳更多高级能力结构(Extended Capabilities)。例如:Advanced Error Reporting (AER)、Power Budgeting、SR-IOV / ARI Capabilities 等
2、ARI 概念
Alternative Routing-ID Interpretation (ARI),即可替代的 ID 路由机制,首次在 PCIe gen3 提出。在 PCIe gen1 和 PCIe gen2 中,Routing IDs, Requester IDs, and Completer IDs 是 16bit 的标识符,由三部分组成,分别是
- 8-bit Bus Number
- 5-bit Device Number
- 3-bit Function Number
由于 PCIe 是端对端设备,作为 Endpoint 类型的设备,只有一个 device,即 device number 恒为 0,此时 5-bit 的 Device Number 没有多大意义,而 3-bit Function Number 只能表示 8 个function,在部分虚拟化场景中(例如 SR-IOV),常常不够用。
基于以上原因,PCIe gen3 提出了 ARI 机制,通过取消 Device Number 字段,采用 8-bit Function Number 和 8-bit Bus Number 组成 Routing IDs, Requester IDs, and Completer IDs,因此占用一个 bus number 的 Endpoint 设备最大可以拥有 256 个 function(PS:一个Endpoint 可以占用多个 bus number)
图 6-13 显示了具有两个 ARI 设备的示例系统拓扑,一个位于 Root Port 下方,一个在 Switch 下方。要访问 ARI Device X 中的扩展功能,Root Port A 必须支持 ARI 转发,并由软件启用。为了访问 ARI Device Y 中的扩展功能,Switch Downstream Port D 必须支持 ARI 转发,并通过软件启用。使用此配置,建议软件不要在 Root Port B 或 Switch Downstream Port C 中启用 ARI 转发。
2.1 是否支持 ARI Forwarding
上面我们提到 ARI Forwarding(ARI 转发)的概念。Root Port 或者 Switch Downstream Port 是否支持该功能,是由 PCI Express Capability Structure 中 Device Capabilities 2 Register 寄存器的 Bit5 决定的。
- ARI Forwarding Supported :仅适用于 Switch Downstream Ports 和 Root Ports;对于其他 function 类型,必须为 0b。如果 Switch Downstream Ports 或 Root Ports 支持此可选功能,则此位必须设置为1b。
2.2 ARI Forwarding 原理
当软件启用 ARI Forwarding 并将其应用于一个下行端口(Downstream Port)时,配置请求处理逻辑会发生改变。原本,设备只允许将 Device Number 为 0 的 Type 1 配置请求转换为 Type 0 请求;而启用 ARI Forwarding 后,这一限制被取消。设备可以将任意 Device Number(0–255)对应的 Type 1 请求转换为 Type 0 请求,从而支持扩展的 Function 编号空间。
关于 Type 1 配置请求和 Type 0 配置请求,可以阅读 PCI 总线学习笔记(五)
2.3 注意事项
强烈建议:软件在设置下行端口(Downstream Port)的 ARI Forwarding Enable 位时,必须确保该端口下挂的设备确实支持 ARI 功能。
如果在下挂的是非 ARI 设备的情况下启用了 ARI Forwarding,那么该设备可能会错误地将不同的 Device Number 解释为自己的不同功能(Function),从而导致多个 Device Numbers 映射到同一个功能,形成所谓的“别名”(aliasing)问题。这种行为往往会造成配置空间访问混乱,并可能引发严重的系统异常或设备功能错误。
从上面的描述我们也可以看出来,一个带 ARI 功能的 PCIe 设备,只需要使能其直连的 Downstream Port 的 ARI Forwarding 功能,
而不需要关心其所在链路上的所有 Downstream Port。因为 Type1 配置请求转 Type 0 只发生在 Downstream Port 到其直连的 PCIe 设备之间
3、ARI Capability
ARI 是一项可选功能。每个 ARI 设备中需各自实现该功能。该功能不适用于根端口(Root Port)、交换机下行端口(Switch Downstream Port)、RCiEP,或根复合事件收集器(Root Complex Event Collector)。
3.1 ARI Capability Header (Offset 00h)
3.2 ARI Capability Register (Offset 04h)
3.3 ARI Control Register (Offset 06h)
4、ARI 配置过程
Linux 下 ARI 配置的一个过程
pci_device_add
--> pci_init_capabilities()--> pci_configure_ari()
这个函数其实挺简单,我们来梳理一下:
/*** pci_configure_ari - enable or disable ARI forwarding* @dev: the PCI device** If @dev and its upstream bridge both support ARI, enable ARI in the* bridge. Otherwise, disable ARI in the bridge.*/
void pci_configure_ari(struct pci_dev *dev)
{u32 cap;struct pci_dev *bridge;if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)return;/* bridge 可以理解为 dev 的 Upstream Port,也就是 Switch 的 Downstream Port */bridge = dev->bus->self;if (!bridge)return;/* 判断 Downstream Port 是否支持 ARI Forwarding */pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap);if (!(cap & PCI_EXP_DEVCAP2_ARI))return;/* * 判断 dev 是否支持 ARI 功能(通过寻找 ARI Capability)* 如果 dev 支持 ARI 功能,则使能其上一级 Upstream Port 的 ARI Forwarding 功能* 否则,关闭其上一级 Upstream Port 的 ARI Forwarding 功能*/if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) {pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,PCI_EXP_DEVCTL2_ARI);bridge->ari_enabled = 1;} else {pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2,PCI_EXP_DEVCTL2_ARI);bridge->ari_enabled = 0;}
}