3. 配置周期类型:Type 0 与 Type 1 及寻址机制

PCIe 配置周期是主机软件(CPU)访问设备配置空间的唯一途径。根据目标设备在总线拓扑中的位置,配置周期分为 Type 0 和 Type 1 两种类型,分别对应 Endpoint 和 Bridge/Switch。理解这两种周期的差异以及 Bus:Device:Function (BDF) 寻址机制,是进行 BAR 空间测试和故障定位的基础。

3.1 配置周期类型概述

配置周期由 Root Complex (RC) 发起,通过 PCIe 总线逐级转发。Type 0 和 Type 1 周期在格式、目标设备以及 Bridge 的转发行为上存在本质区别。

特性 Type 0 配置周期 Type 1 配置周期
目标设备 Endpoint(功能设备) Bridge / Switch(下游端口)
配置空间大小 4 KB(包含 256B PCI 兼容区 + 扩展区) 4 KB(包含 256B PCI 兼容区 + 扩展区)
Bridge 转发行为 不转发(终结于当前总线) 转换为 Type 0 转发到次级总线
典型用途 读写 Endpoint 的 BAR、Capability 结构 枚举下游设备、配置 Bridge 的 Memory/IO 基址
TLP 类型 配置写 0 (CfgWr0) / 配置读 0 (CfgRd0) 配置写 1 (CfgWr1) / 配置读 1 (CfgRd1)
关键点: 软件通过 Type 0 周期直接访问 Endpoint 的配置空间;而访问 Bridge 下游的设备时,必须先发送 Type 1 周期给 Bridge,Bridge 再将其转换为 Type 0 周期发送到次级总线。

3.2 Type 0 配置周期(Endpoint)

Type 0 配置周期用于访问 当前总线上的 Endpoint。当 Root Complex 或 Bridge 发送 Type 0 周期时,该周期不会被转发到其他总线,而是由目标 Endpoint 根据其配置空间地址直接响应。

  • 触发条件: 目标设备的 Bus 号等于当前总线号。
  • 地址格式: 使用 Bus:Device:Function 中的 Device 和 Function 字段,以及配置空间内的寄存器偏移地址。
  • 典型操作: 读取 Vendor ID / Device ID、配置 BAR 寄存器、使能 Memory Space 或 IO Space 位。
测试场景: 在测试 Endpoint 的 BAR 空间之前,必须通过 Type 0 配置写周期将 BAR 寄存器写入全 1,再读取回值以确定 BAR 的大小和对齐要求。这是 BAR 空间测试的第一步。

3.3 Type 1 配置周期(Bridge/Switch)

Type 1 配置周期专门用于访问 Bridge 或 Switch 的配置空间,并且是枚举下游总线层次结构的关键机制。当 Bridge 收到一个 Type 1 配置周期时,它会检查目标 Bus 号是否属于其 次级总线号 (Secondary Bus Number) 到 次级总线上限 (Subordinate Bus Number) 的范围。

  • 转发规则:
    1. 如果目标 Bus 号等于 Bridge 的次级总线号,Bridge 将 Type 1 周期转换为 Type 0 周期,并发送到次级总线。
    2. 如果目标 Bus 号在次级总线号和上限之间,Bridge 将 原封不动地转发 Type 1 周期 到次级总线,由下游的另一个 Bridge 继续处理。
    3. 如果目标 Bus 号不在范围内,Bridge 忽略该周期。
  • 配置 Bridge 自身: 软件通过 Type 1 周期配置 Bridge 的 Primary Bus Number、Secondary Bus Number、Subordinate Bus Number 以及 Memory/IO 基址和限制寄存器。
常见错误: 如果 Bridge 的次级总线号配置错误,或者 Subordinate Bus Number 设置过小,会导致 Type 1 周期无法正确转发,造成下游设备无法被枚举。这是 PCIe 链路调试中常见的“设备丢失”原因之一。

3.4 配置周期寻址机制:BDF

每个 PCIe 设备在系统中由唯一的 Bus:Device:Function (BDF) 三元组标识。配置周期通过 BDF 寻址,确保软件能够精确访问到特定功能。

字段 位宽 范围 说明
Bus Number 8 位 0 - 255 标识设备所在的 PCIe 总线号。0 通常为 Root Complex 内部总线。
Device Number 5 位 0 - 31 标识总线上的物理设备。每个总线最多支持 32 个设备。
Function Number 3 位 0 - 7 标识设备内的功能单元。支持多功能设备(如集成显卡 + 音频)。

在软件层面(如 Linux 内核或 UEFI),BDF 通常表示为 Bus:Device.Function 格式,例如 01:00.0 表示 Bus 1、Device 0、Function 0。

3.5 配置周期寻址与转发流程(SVG 架构图)

下图展示了从 Root Complex 发起一个配置周期,经过 Switch 转发,最终到达目标 Endpoint 的完整流程。图中清晰区分了 Type 0 和 Type 1 周期的使用场景。

PCIe 配置周期寻址与转发流程 PCIe 配置周期寻址与转发流程 Root Complex (RC) Type 1 周期 (Bus=1) Switch (Bridge) Primary Bus=0, Secondary Bus=1, Subordinate Bus=2 转换为 Type 0 (Bus=1) Endpoint 1 (BDF=01:00.0) 转发 Type 1 (Bus=2) 下游 Bridge (Bus=2) 转换为 Type 0 Endpoint 2 (BDF=02:00.0) 说明: Type 1 周期用于跨总线寻址;当到达目标总线时,Bridge 将其转换为 Type 0 周期,由 Endpoint 直接响应。

3.6 配置周期访问示例(代码片段)

以下代码展示了在 Linux 用户空间通过 sysfs 接口读取指定 BDF 设备的配置空间。这是硬件测试中验证配置周期是否正常工作的常用方法。

# 读取 BDF=01:00.0 的 Vendor ID 和 Device ID(偏移 0x00)
# 使用 lspci 工具(内部通过 sysfs 或 /dev/port 发起配置周期)
lspci -s 01:00.0 -xxx

# 或者直接读取 sysfs 文件
cat /sys/bus/pci/devices/0000:01:00.0/config | xxd | head -n 1

# 使用 setpci 工具直接读写配置空间寄存器
# 读取 Vendor ID (偏移 0x00, 2 字节)
setpci -s 01:00.0 0x00.w

# 写入 BAR0 寄存器(偏移 0x10, 4 字节)进行大小探测
setpci -s 01:00.0 0x10.l=0xffffffff
setpci -s 01:00.0 0x10.l   # 读取回值,取反加 1 得到 BAR 大小
测试建议: 在测试环境中,使用 setpci 对 BAR 寄存器进行“写全 1 再读回”操作时,务必先记录原始值,测试完成后恢复,避免设备驱动因 BAR 地址被破坏而崩溃。

3.7 配置周期类型对比总结

对比维度 Type 0 配置周期 Type 1 配置周期
TLP 格式 CfgWr0 / CfgRd0 CfgWr1 / CfgRd1
目标设备 Endpoint Bridge / Switch
Bridge 行为 不转发,终结 检查 Bus 范围,决定转发或转换
寻址范围 当前总线 跨总线(次级到上限)
测试关注点 BAR 大小探测、Capability 遍历 Bridge 寄存器配置、总线枚举完整性