深入理解 PCIe 协议中 BDF(Bus/Device/Function)分配与管理机制
本篇文章,适用于对 PCI 和 PCIe 协议有一定了解的读者,不了解的同学,可以先阅读其它 PCI 相关文章
1、引言
通过前面章节的学习,我们对 PCI/PCIe 协议已经有了一个整体的把握。现在我们来讨论一个更深入的问题,每个设备是如何知道自己的 BDF 的?是由硬件决定还是软件决定的呢?
2、 PCI 中的 BDF
首先关于 Bus 号,当一个 “配置访问请求” 从 HOST 主桥发出,有且只会传递到与其直连的一级 Bus 总线上。接着再由这一级 Bus 总线上的桥片中的 Primary、Secondary、Subordinate Bus Number 决定是否要接着向下转发。而桥配置空间中的 Primary、Secondary、Subordinate Bus Number 的值都是可配置的。
关于 Device 号,在 PCI 总线学习笔记(五) 一章中,有详细讲解,这里不再赘述。PCI 协议中的 Device 号,完全是由硬件连线决定的。
3、 PCIe 中的 BDF
-
Host Bridge 中的两个 Downstream Ports 设备,是如何他们自己分别是 Device 几呢?
答:是由硬件设计决定的。同样的,Switch 中的 Downstream Ports 设备的设备号,也都是由硬件设计决定的。 -
当访问 Bus 1 上的设备时,Host Bridge 发出的请求是如何转发的?
答:这实际上和 PCIe 设备枚举的流程有关。通常 PCIe 使用深度优先遍历(DFS)进行枚举设备。在枚举 BDF(0,0,0)后,会接着尝试访问 BDF(1,0,0)、访问 BDF(2,0,0),在枚举的过程中,会不断修改桥设备(除 endpoint 设备外的设备)的中的 Primary、Secondary、Subordinate Bus Number Register。这三个寄存器,决定了 Bus 号的路由。例如:
a. 当枚举到 BDF(0,0,0)后,会设置该设备的 Primary Bus = 0、Secondary Bus = 1、Subordinate Bus = 0xff
b. 当枚举 BDF(1,0,0)时,只会从 Device 0 这个 Downstream Ports 路由。因为硬件(Switch)根据 Primary、Secondary、Subordinate Bus Number 知道了 Bus 1 在 Device 0 这个 Downstream Ports 下面。
c. 接着会将该设备的 Primary Bus = 1、Secondary Bus = 2、Subordinate Bus = 0xff…
d. 循环往复,完成整颗 PCIe 树的设备枚举
PCIe 设备枚举过程的代码详解,参考:PCI 总线学习笔记(三)
理论上说,如果强制把 Device 1 的 Primary、Secondary、Subordinate Bus Number 改成和 Device 0 一样的(Device 0 强制修改成其它值),访问 Bus 1 时,会从 Device 1 这个 Downstream Ports 路由,那么整棵树形结构就会发生变化。
3、总结
PCI / PCIe 中:
- RC 发出的访问
- Endpoint 设备需要经过各级桥设备的 ID 路由来响应 RC
- 与 RC 直连的桥设备,不需要经过路由,直接根据硬件的 Device 号响应 RC
- 不与 RC 直连的桥设备,依赖其上级桥设备的 ID 路由响应 RC。例如,当前桥设备为 A,该桥设备的上一级桥设备为 B。只要 RC 发出的访问被 B 接收到、并且在 B 的 Primary、Secondary、Subordinate Bus Number 范围内,那么桥设备 A 就一定能响应 Bus 号为 Secondary + 1 的访问请求,由硬件决定