PCIe枚举知识

目录

1.OS Enum流程

1.0先验知识

1.1枚举概述

1.2 设备扫描

1.2.1 图中名词解释

1.2.2 设备扫描深度讲解

1.2.3 bdf号详细解释

1.3 Linux内核---枚举

1.3.1 PCIe枚举流程入口

2.交换相关配置

3.故障定位

3.1 枚举相关定位手段


1.OS Enum流程

1.0先验知识

参考博客:【PCIE-3】---PCIE设备的枚举扫描(经典好文) - 一粒厘米 - 博客园

【PCIE-4】---PCIE中部分概念或问题总结(很基础很重要) - 一粒厘米 - 博客园

1)系统如何判断PCIE设备是否在位?

BIOS代码在枚举设备的时候,会去读每个设备的VID,如果读到的不是FFFF,则表示该位置有设备存在,若为FFFF,则表示设备不存在。DID&VID是出厂的时候就固定在PCIE设备配置空间中的数据,表示每个不同的设备,同理,我们在BIOS中也可以通过判断这个ID值来寻找指定的PCIE设备

2)设备中的配置空间的数据一开始就有嘛?谁写的?

 每个设备在出厂时,其配置空间中的值都有一些default值,枚举该设备时为每个设备分配BDS号和内存资源时,会再写入部分值。

3) Bus号,Dev号,和Fun号与硬件有关系嘛?硬件链接与BDS号的分配是否有关

Dev和Fun号应该是和硬件设计有关系,也就是硬件就已经固定,软件的枚举过程是更多的是在分配Bus号。为什么这么说呢?这里要着重讲解下:

PCI是总线结构,而PCIE已经是点对点机构,这个点对点结构很重要,待会重点讲到。首先先来看下一个典型的Pcie系统框图如下:

从CPU出来,有一个Root Compex(RC),从PCIE设备断端来看的,我更倾向于简单的把这个RC理解为一个HostBridge,这样可能大家都会理解的更加清楚。OK,从RC出来,最典型也是最简单的结构就是一个Root Port和一个Endpoint设备直接组成一个点对点设备,重点来了哈,这里面我们仅仅挂载了一个端点设备,但当一个root port仅和一个EndPoint设备相连时,该EndPoint设备就需要一条Bus,我和同事讨论了下,大致原因是从CPU出来的每个port都是一个Bridge,有一个Bridge就要对应一条Bus,即使该Bus下仅有一个Dev,也需要给他单独分配一个Bus号。

  上面介绍了一个Root Port和一个EndPont设备相连时的情况,这是最典型的PCIE点对点结构,现在讨论一个Port下挂载多个设备时要怎么做? 这种情况下一般就需要Switch了,Switch物理上一般是一个芯片,我更倾向于把他理解为一个分线器,RootPort对应一条Bus,该Bus由于Switch的存在可以挂载多个dev,也就是对应多个Dev的情况。

  那么问题中所说的每个设备的Dev和Fun是由硬件固定的是怎么回事呢?那加入这两个固定,对于到软件枚举又如何对应呢?情况大致是这样:

 a. Dev和Fun硬件固定,这个是由硬件决定,为何这样定,后续我做实验后贴数据上来,现在我们就这样认为;

  b. 上面已经介绍了PCIE点对点结构,从一个Port出来即使仅有一个设备,也需要给该设备重新分配一条Bus。那么假设我插入了两个设备,在没有挂接到switch上时,这两个设备正如上面所说,组成了root port - endpoint dev的两个设备对,每个设备在枚举时,都会被重新分配一条Bus号,这种情况不会冲突。

  c. 假如这两个设备接在了同一个Switch上,原本应该是Switch属于某个Bus下一个分线器,分别挂接来不同的设备,亦有不同的Dev和Fun。那么在这种情况下,如果Dev和Fun一致,枚举软件自动会把这Switch的两个port再次当成一个与Root Port类似的port。每个Port也可当作一个Bridge来使用,由于两个设备Dev和Fun一样,所以会再给这两个设备分配 两个新的Bus号,以表示区别,其他的设备则按原计划枚举扫描。大概是这样的过程。

4)Bridge和Device的区别?

 PCIE设备树的实现,离不开Bridge,我个人更倾向于简单一点去看带着Bridge和Device,或许可以这样说:Bridge是一条Bus的管理者,当你看到一个Bridge的时候,也会对应的有一条Bus。那Device就简单的多了,简单的一个终端设备。不过目前在我看来Bridge某种意义上也可以算的上一种Device

因为在枚举扫描的时候,接下来扫到的这个是什么?你假设它为Bus1,Dev0,Fun0,然后发现有设备,去读了配置空间的Header和ClassCode后才知道这是一个Bridge还是device,但实际上你已经假设它为一个Device了,不是嘛?哈哈

5)Device和Function的区别?

对于插入的某个设备,其Function号对应的就是它不同的功能

6)Bridge/Host Bridge,Root Complex, Root port这些要怎么理解(以下解释来源于PCIE Spec)

Host bridge的概念:Root Complex中用来链接一个主CPU或多个CPU和一个层次结构的一个部分

Port 的概念:1.逻辑上: 位于部件和一个PCIE链路之间的接口。 2. 物理上: 位于同一个芯片上用来定义一个链路的一组发射器和接收器。

Root Port的概念:一个位于Root Complex上通过相关联的虚拟PCI-PCI Bridge映射一个层次结构整体部分的的PCIE Port

Root Complex的概念: 一个的系统元素,包含一个Host Bridge, 0个或多个集成EndPoints的Root Complex, 0个或多个Root Complex时间收集器,0个或多个Root Ports

Switch的概念:一个定义好的用来连接两个或多个Ports且允许数据包在不同Ports之间被路由转发的一个系统元素。通过配置软件,一个switch也被配置为一组虚拟PCI-to-PCI Bridges的集合

Link的概念:两个Ports和他们之间所连接Lanes的集合。一个Link是一个双工通信通道在两个部件之间。

Lane的概念:一组不同的信号对,一对用来传送,一堆用来接收。由于PCIE使用差分信号传输,一条lane四条线,两条线组成一对,供发送。另外两条接收!

7)PCI总线模型和PCIE是点对点模型,要怎么理解?

PCI总线模型: 在传统的PCI总线模型中,一个设备通过在Bus上判断DEVSEL(设备选择)来认领一个请求。如果在一段时钟周期后没有设备认领一个请求,这个请求就被放弃。

PCIE点对点模型:PCI是一种点对点的传输模型,不像PCI总线那样,在总线上有平等认领请求的机制。所有的传送总是由一个Device发给Link上的另外一个Device。所以,对于所有接收方来说,接收方将会直接判断这个请请求是否要被认领。

8)EndPint是否可以直接访问另外一个EndPoint

在PCIE这种点对点的模型中,设备之间之间的互联访问是可以的。  

情况一:不需要CPU参与

最典型的应用就是在一个带有DMA功能的Switch下,挂载两个EP,CPU需要首先配置DMA控制器,包括设置一些源地址,目标地址,传输数据以及数据量。然后每个设备发起DMA传输的时候,会直接透过Switch中的DMA控制器,发数据到另外一个设备,这个过程不需要CPU干预

情况二:CPU参与

这个过程就相对来说简单了,CPU从一个PCIE设备中读取出要发送的数据,然后直接发送给指定的目的PCIE设备节点即可。

1.1枚举概述

PCIe设备的枚举过程指的是:系统在上电后自动扫描并且发现PCIe总线上面的所有设备,并且对其进行初始化和配置,以便操作系统和应用程序可以和这些设备进行通信。

枚举的一般步骤如下:

1.设备扫描:当主机启动的时候,开始对PCIe总线进行扫描,已识别连接到总线上面的所有设备

2.设备初始化:如果检测到一个设备,主机控制器会为该设备分配一个唯一的设备号,并初始化该设备

3.功能性枚举:如果PCIe设备支持多个功能,系统将为每一个功能分配唯一的功能号

4.配置空间访问:主机通过配置事务(Config Transactions)访问设备的配置空间

5.Bar分配:主机将分配适当的地址范围给基地址寄存器(Bar),确保设备能够在地址空间中正确寻址。

6.中断向量分配:主机可能会为设备分配中断向量,以便设备可以通过中断通知主机系统特定事件。

1.2 设备扫描

1.2.1 图中名词解释

1)Root Complex:根桥设备,CPU和PCIe拓扑之间的接口,负责PCIe报文的解析和生成,RC会将CPU的request转换成PCIe的四种请求(Configuration,Memory,I/O,Message,也就是PCIe的配置,内存,I/O,消息);

2)Host Bridge:CPU与PCIe拓扑之间的接口,通常集成在Root Complex中,将CPU的内存访问请求为PCIe事务,管理PCIe总线的初始化与枚举过程

3)Primary Bus Number:主总线号,表示桥设备上游总线号,即桥连接的上一级总线的编号,用于标识桥所属的根总线 4)Secondary Bus Number:次总线号,指桥设备直接连接的下游总线号,是桥下游第一个PCI总线的编号 5)Subordinate Bus Number:从属总线号,是该桥下所有总线中最大的总线号,代表以该桥为根的子树中,总线号的最大值

6)Integrate EP:集成在SoC(片上系统)中的PCIe终端设备,无需额外PCIe控制器,直接作为Endpoint连接到PCIe总线

7)Graphics Card:基于PCIe接口的独立显卡,用于图形渲染NVMe SSD:基于NVMe协议的固态硬盘,通过PCIe接口连接

8)Network Interface Card (NIC):网卡,用于网络通信

1.2.2 设备扫描深度讲解

PCIe设备的扫描基于深度优先算法,也就是对每一个可能的分支路径深入到不能再深入为止:

1.Host主桥扫描Bus 0 上面的设备(在处理器中,一般将RC中与Host Bridge相连接的总线命名为Bus 0),系统首先会忽略Bus 0上的Integrate EP等不会挂接桥的设备,主桥发现Bridge1之后,将Bridge1下面的Bus定为Bus1,系统将初始化Bridge1的配置空间,并将该桥的Primary Bus Number和Secondary Bus Number寄存器分别设置为0和1,以表明Bridge1的上游总线是0,下游总线是1,由于还无法确定Bridge1下挂载设备的具体情况,系统暂时将Subordinate Bus Number设置为0xFF;

2.系统开始扫描Bus 1,将会发现Bridge3,并且发现这是一个switch设备。系统将Bridge3下面的Bus定为Bus 2,并且将该桥的Primary Bus Number和Secondary Bus Number寄存器分别设置为1和2,和上一步一样暂时把Bridge3的Subordinate Bus Number设置为0xFF

3.系统继续扫描Bus 2,将会发现Bridge4,继续扫描,系统会发现Bridge下面挂载的NVMe SSD设备,系统将Bridge4下面的Bus定为Bus 3,并且将该桥的Primary Bus Number和Secondary Bus Number寄存器分别设置为2和3,因为Bus 3 下面挂的是端点设备,不会再有下游总线,因此Bridge4的Subordinate Bus Number的值可以确定为3;

4.完成Bus 3的扫描后,系统返回到Bus 2继续扫描,会发现Bridge5。继续扫描,系统会发现下面挂载的NIC设备,系统将Bridge5下的Bus设置为Bus 4,并将该桥的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成2和4,因为NIC同样是端点设备,Bridge5的Subordinate Bus Number的值可以确定为4;

5.除了Bridge4和Bridge5以外,Bus 2下面已经没有其他设备,因此系统返回到Bridge3,Bus4是这个Bridge分支枚举到的最后一个bus号,因此将Bridge3的Subordinate Bus Number设置为4,Bridge3的下游设备都已经扫描完毕,继续向上返回到Bridge1,同样将Bridge1的Subordinate Bus Number设置为4

6.系统返回到Bus 0继续扫描,会发现Bridge2,系统将Bridge2下面的Bus号定为Bus 5,并将Bridge2的Primary Bus Number 和 Secondary Bus Number分别设成0和5,Graphics card也是端点设备,因此Bridge2 的Subordinate Bus Number的值可以确定为5;至此,挂在PCIe总线上的所有设备均被扫描到,枚举过程结束。

设备扫描完成后系统获得了完整的总线拓扑结构,图中各个设备的bdf(bus,device,function)号如下:

1.2.3 bdf号详细解释

1)BDF号组成

Bus(总线号)Device(设备号)Function(功能号)
范围0-255(8位)0-31(5位)0-7(3位)
含义表示设备所在的PCIe总线层级,通过PCIe桥(Bridge)划分表示总线上的物理插槽位置,从0开始编号表示设备支持的多功能,比如声卡和网卡集成在同一个物理设备中

2)编号规则

总线号(Bus) 根总线(Root Bus):固定为 0。 下游总线:由 PCIe 桥的配置空间决定: Primary Bus:桥的上游总线号(例如桥本身在 Bus 0)。 Secondary Bus:桥的下游第一个总线号(例如 Bus 1)。 Subordinate Bus:桥下所有总线的最大编号(例如 Bus 10)。 示例:

Root Complex (Bus 0)
├─ PCIe Bridge 1 (Bus 0, Secondary=1, Subordinate=5)
│  ├─ Device 1 (Bus 1:00.0)
│  └─ Device 2 (Bus 1:01.0)
└─ PCIe Bridge 2 (Bus 0, Secondary=6, Subordinate=10)
   └─ Device 3 (Bus 6:00.0)

设备号(Device)

  • 每个 PCIe 插槽或集成设备分配唯一的设备号(0-31)。

  • 物理位置决定编号,例如:

    • 主板上 PCIe 插槽 1 → Device 0。

    • 插槽 2 → Device 1,依此类推。

功能号(Function)

  • 单功能设备:固定为 0(例如 00:01.0)。

  • 多功能设备

    :每个功能分配独立编号(0-7)。

    • 例如:显卡支持显示和音频 → 00:02.0(显示)、00:02.1(音频)。

1.3 Linux内核---枚举

1.3.1 PCIe枚举流程入口

2.交换相关配置

1)上报顺序(BUS号)-----外设的上报------按照前面的流程当前按照设备device ID进行深度scan,则交换可以修其下行口dev index来改变扫描顺序

2)预留资源。上行口可以提前申请资源,但是本质通过虚拟外设(占位符),不建议使用

3.故障定位

3.1 枚举相关定位手段

参考博客:pcie枚举失败的几个调试工具 - 轻轻的吻 - 博客园

枚举过程可能出问题,比如设备识别失败,资源分配冲突。可以利用下面这些方法,定位问题环节和原因。

  • BIOS:作为计算机启动时最先运行的软件,在枚举相关定位中起到基础作用。

    • acpi(Advanced Configuration and Power Interface):高级配置与电源接口规范。dsdt(Differentiated System Description Table)是ACPI规范中的一个表,BIOS通过ACPI机制管理系统硬件资源配置与电源管理,DSDT记录硬件配置信息,供操作系统使用 。

    • 地址空间:BIOS负责初始化和配置系统的地址空间,确定硬件设备在内存地址空间中的映射位置,这对设备枚举时识别和定位设备很关键 。

  • OS(操作系统):在设备枚举定位方面有多种手段。

    • lspci -vv:是Linux系统下用于查看PCI及PCIe设备详细信息的命令。通过它可以获取设备的厂商ID、设备ID、子系统ID、驱动信息等,有助于定位枚举问题 。

    • cat /proc/iomem/proc/iomem是Linux系统中记录系统内存映射信息的文件,使用cat命令查看该文件内容,能了解硬件设备的I/O内存地址分配情况,判断设备枚举时地址分配是否正确 。

    • dmesg&内核代码dmesg用于打印内核环形缓冲区中的消息,在设备枚举过程中,会输出大量设备探测、驱动加载等相关信息,结合内核代码分析这些信息,可定位枚举过程中出现的问题 。

    • acpi:同BIOS中的acpi,操作系统利用ACPI规范获取硬件配置信息,dsdt表内容在系统运行时也供操作系统参考,辅助设备枚举和管理 。

  • 交换日志:记录系统运行过程中的各种事件和操作信息。trace即追踪功能,通过对交换日志进行追踪分析,可以获取设备枚举过程中的详细操作步骤和状态变化,帮助排查枚举过程中可能出现的异常情况 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值