下面的文章将简要分析一下我们常用的电脑在启动过程中是如何进行pcie device枚举,发现每个device,同时给每个device分配合理的b:d.f的,我们将通过举几个和pcie device交互的例子说明。有的朋友可能会问,该枚举是在link up进入L0,然后协商flow control等信息link logically up之后做的第一件事情吗?整个过程一般会持续多少时间,例如大概几百ms还是几秒钟?有的时候会卡住吗?会有timeout超时机制设置吗?如果路径中间经过pcie switch咋办?我们也会涉及一下上述内容。
执行者:不是 PCIe 协议本身,而是 BIOS/UEFI 软件层(PCI Bus Driver)目的:发现所有端口下的设备,并给设备分配 Bus/Device/Function 编号与资源(BAR space)。
PCIe 协议只负责:链路训练(TS1/TS2)、进入 L0、FEC、Lane Negotiation、Scrambling、Symbol Lock、Flow Control Credits 初始化等。
设备枚举属于“configuration space access”,是软件行为,不是 PCIe 链路层功能。
很多工程师误以为 BIOS 枚举设备是通过 MemRd/MemWr TLP。
✔ 正确:使用 Config Type 0 / Type 1 TLP
Type 0 Configuration Read/Write TLP:访问同一个 bus上的设备 (Device/Function)
Type 1 Configuration Read/Write TLP:访问下层 bus(例如 PCIe Switch 下的子 Bus)
例如 BIOS 读 VendorID:
下图是使用SerialTek PCIe 5.0/6.0协议分析仪看到开机后CPU发了第一个MesD_local后大概过了400ms进开始进行pcie device枚举的过程。
PCIe LTSSM:
Detect
Polling(TS1/TS2)
Configuration(TS1/TS2 + Lane/Speed negotiation)
Recovery
L0 🔥
Flow Control 初始化(InitFC1 / InitFC2)
链路逻辑 UP
✨ BIOS 只有在 Link Training 完全结束、进入 L0、FC credit 也 ready 后才可以开始发 PCIe TLP。
因此:
✔ 设备枚举是 Link Up 完成后的第一批软件操作之一。
Boot 时,BIOS 从:
Bus 0 → Device 0–31 → Function 0–7
依次尝试访问:
若设备不存在: → 返回 0xFFFF_FFFF
若设备存在: → 返回 VendorID / DeviceID
假设 CPU Root Port 出现在:
BIOS 识别这是一个 PCIe Root Port,于是给这个 Root Port 下的新 Bus 指定一个编号:然后 BIOS 开始扫描 Bus = 1 的设备。
假设结构:
枚举过程:Root Port 被枚举(Bus 0, Dev x)
BIOS 分配 Secondary Bus = 1
BIOS 在 Bus 1 读 VendorID
发现这是 PCIe Switch(Device=0x10B5 for PLX/Avago/Broadcom)
配置 Switch 的 Primary/Secondary/Subordinate Bus
对每个 Downstream Port 再给一个新 Bus 号,例如:
BIOS 再依次扫描 Bus 2、Bus 3、Bus 4、Bus 5…
BIOS 发:
Config Read Type 0 (0:1:0 offset 0x00)
返回:
→ 说明这是 Intel 网卡。
值示例:| Class Code | 设备类型 |
|---|---|
| 0x010802 | NVMe |
| 0x030000 | VGA / GPU |
| 0x060400 | PCIe-to-PCIe Bridge (Switch) |
| 0x0C0330 | USB 3.0 controller |
BIOS 根据 Class Code 决定如何深入扫描。
BIOS 写 BAR = 0xFFFF_FFFF,然后读回来。
如果设备返回:
→ 表示需要 4KB MMIO BAR space。BIOS 用此信息分配地址。
| 项目 | 耗时 |
|---|---|
| PCIe Link Training (TS1/TS2 + FEC lock) | 5–50 ms PER PORT |
| 枚举、高级扫描、BAR 分配 | 10–200 ms |
| PCIe Switch 多层拓扑 | 最多 300–800 ms |
总计通常:100ms~1 秒之间。
如有大量 Switch + 多层拓扑(大服务器系统)可能达到 2–3 秒。
常见超时:
配置读超时(无响应设备 → 返回 0xFFFF_FFFF)
Link Training timeout(链路一直在 Recovery 状态 → UEFI 有 100ms~500ms 的重试)
BAR 分配失败(MMIO 资源不足)
设备用 DPC / LTSSM 死循环导致 Root Port 死等
Link Training Timeout:100ms~500ms
Config TLP Timeout:20ms~50ms
Switch 热插拔端口 Recovery 超时:≈100 ms
因此:
✔ 枚举大概率不会“无限卡死”,都会降级、跳过设备、或者报错继续。
工程师常碰到:
Retimer/Switch training 不稳定 → link 一直在 Polling/Recovery 循环
BIOS 没有足够的地址空间分配给 BAR(尤其 GPU 或 SmartNIC)
PCIe device 还没上电 or VSEC 读不到
FLR resetting 需要时间
这些都会导致“有时能枚举、有时不能枚举”。
| 你的问题 | 回答 |
|---|---|
| 枚举是通过 TLP MemRd 实现的吗? | ❌ 不是。使用 Config Read/Write TLP |
| 枚举何时发生? | Link Up → Flow Control Ready 之后立刻进行 |
| 枚举耗时多少? | 100ms ~ 1 秒(大型系统可达 3 秒) |
| 会卡住吗? | 有 timeout,会跳过问题设备 |
| 如何为 switch 分派 B:D.F? | BIOS 为每个 downstream port 分配一个新的 Bus number,递归扫描 |
| 和直连设备的差异? | 增加 Type1 Config TLP,并分层 bus 扫描结构 |
https://pan.baidu.com/s/18_c11aeFhSBe2qa-jUFs_Q?pwd=mm9y 提取码: mm9y
如果你有其任何关于PCIe5&6.0, CXL, NVMe/NVMoF, NAND, DDR5/LPDDR5以及UFS测试方面的我问题想咨询,请访问:访问www.saniffer.cn / www.saniffer.com 访问我们的相关测试工具和产品;或者添加点击左下角“阅读原文”留言,或者saniffer公众号留言,致电021-50807071 / 13127856862,sales@saniffer.com。