参考及疑问
参考文献
- 《PCI+E体系结构导读》 P4.1.4, P4.2
 - PCIE学习笔记-知乎参考
 
疑问
在开始之前,有几个疑问:
- PCIE是端到端的数据传输,那么 PCIE链路是如何扩展的?
 - 如何从Linux环境下来 分析自己的PCIE链路(实战)?
 
在分析完后,也存在了几个疑惑:
- 软件代码是如何初始化的?
 - 我的主机里边,为啥总线没有bus2,直接从bus1 到了bus3(BUS号不连续?)
 - 在前边我们知道,非ARI设备,Device的编号间隔是8, 为什么我的设备怎么这么奇怪?
00:00.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148000:00.2 IOMMU: Advanced Micro Devices, Inc. [AMD] Device 148100:01.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:01.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:01.3 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:02.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:03.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:03.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:04.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:05.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:07.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:07.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 1484
 
Pcie链路的扩展
Switch的作用
在《PCI+E 体系结构》4.1.4 链路扩展 章节中描述:
PCIE 的链路通信是 端到端的数据传输, 在一条PCIE链路中,分别是发送和接收设备,因此产生了PCIE Switch进行扩展
Switch设备就和USB Hub一样,支持 1个上游端口(连接主机或者RC), 2-n个下游端口(扩展口)。
因此,现代计算机的结构类似如下:

总结:
- CPU平时非常的忙,便把很多事交给(Root Complex 简称RC)来干,RC可以访问内存,通过内部PCIe总线以及若干个PCIe Bridge,扩展出若干个其他的PCIe端口, RC内部十分复杂。
 - PCIe终端设备称为 Endpoint,比如 PCIe SSD,PCIe 网卡等等,Endpoint可以挂载到 RC 上,也可以挂载到Switch上。
 - switch(交换器)扩展了PCIe端口,将一个PCIe端口扩展为若干个,靠近RC的端口称为上游端口,扩展出来的端口称为下游端口。下游端口可以挂载其他switch或者Endpoint,并且对他们进行管理。
 - 从上游过来的数据,它需要鉴定:
 
1.是否是传给自己的数据,如果是便接收。
2. 是否是自己下游端口的数据,如果是便转发 
3.如果都不是,便拒绝。
- 从下游端口挂载的Endpoint传给RC的数据,switch也会检查并转发。
 
PCI-e总线的扩展
sec - secondary bus,下一级bus
pri - primary bus, 上一级bus
sub - subordinate bus,最末级bus。
分析自己的PCIE链路
基础信息
X86下PCIE的结构如下:
系统信息
根据系统 可以分析到:
(base) baiy@inno-MS-7B89:vf_testpcie$ lspci00:00.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148000:00.2 IOMMU: Advanced Micro Devices, Inc. [AMD] Device 148100:01.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:01.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:01.3 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:02.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:03.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:03.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:04.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:05.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:07.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:07.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148400:08.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:08.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148400:08.2 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148400:08.3 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148400:14.0 SMBus: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller (rev 61)00:14.3 ISA bridge: Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge (rev 51)00:18.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144000:18.1 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144100:18.2 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144200:18.3 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144300:18.4 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144400:18.5 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144500:18.6 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144600:18.7 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 144701:00.0 Non-Volatile memory controller: Sandisk Corp Device 500603:00.0 USB controller: Advanced Micro Devices, Inc. [AMD] Device 43d5 (rev 01)03:00.1 SATA controller: Advanced Micro Devices, Inc. [AMD] Device 43c8 (rev 01)03:00.2 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 43c6 (rev 01)20:00.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 43c7 (rev 01)20:01.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 43c7 (rev 01)20:04.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 43c7 (rev 01)22:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 15)26:00.0 VGA compatible controller: NVIDIA Corporation Device 1f82 (rev a1)26:00.1 Audio device: NVIDIA Corporation Device 10fa (rev a1)27:00.0 Non-Essential Instrumentation [1300]: Advanced Micro Devices, Inc. [AMD] Device 148a28:00.0 Non-Essential Instrumentation [1300]: Advanced Micro Devices, Inc. [AMD] Device 148528:00.1 Encryption controller: Advanced Micro Devices, Inc. [AMD] Device 148628:00.3 USB controller: Advanced Micro Devices, Inc. [AMD] Device 149c28:00.4 Audio device: Advanced Micro Devices, Inc. [AMD] Device 148730:00.0 SATA controller: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] (rev 51)31:00.0 SATA controller: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] (rev 51)(base) baiy@inno-MS-7B89:vf_testpcie$ ls /sys/bus/pci/devices/ -l0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.00000:00:00.2 -> ../../../devices/pci0000:00/0000:00:00.20000:00:01.0 -> ../../../devices/pci0000:00/0000:00:01.00000:00:01.1 -> ../../../devices/pci0000:00/0000:00:01.10000:00:01.3 -> ../../../devices/pci0000:00/0000:00:01.30000:00:02.0 -> ../../../devices/pci0000:00/0000:00:02.00000:00:03.0 -> ../../../devices/pci0000:00/0000:00:03.00000:00:03.1 -> ../../../devices/pci0000:00/0000:00:03.10000:00:04.0 -> ../../../devices/pci0000:00/0000:00:04.00000:00:05.0 -> ../../../devices/pci0000:00/0000:00:05.00000:00:07.0 -> ../../../devices/pci0000:00/0000:00:07.00000:00:07.1 -> ../../../devices/pci0000:00/0000:00:07.10000:00:08.0 -> ../../../devices/pci0000:00/0000:00:08.00000:00:08.1 -> ../../../devices/pci0000:00/0000:00:08.10000:00:08.2 -> ../../../devices/pci0000:00/0000:00:08.20000:00:08.3 -> ../../../devices/pci0000:00/0000:00:08.30000:00:14.0 -> ../../../devices/pci0000:00/0000:00:14.00000:00:14.3 -> ../../../devices/pci0000:00/0000:00:14.30000:00:18.0 -> ../../../devices/pci0000:00/0000:00:18.00000:00:18.1 -> ../../../devices/pci0000:00/0000:00:18.10000:00:18.2 -> ../../../devices/pci0000:00/0000:00:18.20000:00:18.3 -> ../../../devices/pci0000:00/0000:00:18.30000:00:18.4 -> ../../../devices/pci0000:00/0000:00:18.40000:00:18.5 -> ../../../devices/pci0000:00/0000:00:18.50000:00:18.6 -> ../../../devices/pci0000:00/0000:00:18.60000:00:18.7 -> ../../../devices/pci0000:00/0000:00:18.70000:01:00.0 -> ../../../devices/pci0000:00/0000:00:01.1/0000:01:00.00000:03:00.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.00000:03:00.1 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.10000:03:00.2 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.20000:20:00.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:00.00000:20:01.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:01.00000:20:04.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:04.00000:22:00.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:01.0/0000:22:00.00000:26:00.0 -> ../../../devices/pci0000:00/0000:00:03.1/0000:26:00.00000:26:00.1 -> ../../../devices/pci0000:00/0000:00:03.1/0000:26:00.10000:27:00.0 -> ../../../devices/pci0000:00/0000:00:07.1/0000:27:00.00000:28:00.0 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.00000:28:00.1 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.10000:28:00.3 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.30000:28:00.4 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.40000:30:00.0 -> ../../../devices/pci0000:00/0000:00:08.2/0000:30:00.00000:31:00.0 -> ../../../devices/pci0000:00/0000:00:08.3/0000:31:00.0(base) baiy@inno-MS-7B89:vf_testpcie$ lspci -t-[0000:00]-+-00.0+-00.2+-01.0+-01.1-[01]----00.0+-01.3-[03-25]--+-00.0| +-00.1| \-00.2-[20-25]--+-00.0-[21]--| +-01.0-[22]----00.0| \-04.0-[25]--+-02.0+-03.0+-03.1-[26]--+-00.0| \-00.1+-04.0+-05.0+-07.0+-07.1-[27]----00.0+-08.0+-08.1-[28]--+-00.0| +-00.1| +-00.3| \-00.4+-08.2-[30]----00.0+-08.3-[31]----00.0+-14.0+-14.3+-18.0+-18.1+-18.2+-18.3+-18.4+-18.5+-18.6\-18.7
分析方式
确定主桥个数
首先,确定当前主机分配了几个主桥,以及每个主桥的资源信息
dmesg | grep “PCI Root Bridge”    查看系统启动信息,可以知道 当前RC下边挂了几个Swiitch(大部分机器都只有一个SEG,所以不管多少主桥,BUS号都在00-ff之间)
(base) baiy@inno-MS-7B89:~$ dmesg | grep "PCI Root Bridge"[ 0.500591] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])PCI总线00的资源信息[ 0.500591] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])[ 0.502397] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI HPX-Type3][ 0.506523] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug PME LTR][ 0.510513] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug AER PCIeCapability][ 0.514399] acpi PNP0A08:00: [Firmware Info]: MMCONFIG for domain 0000 [bus 00-3f] only partially covers this bridge[ 0.518652] PCI host bridge to bus 0000:00[ 0.522393] pci_bus 0000:00: root bus resource [io 0x0000-0x03af window][ 0.526392] pci_bus 0000:00: root bus resource [io 0x03e0-0x0cf7 window][ 0.530392] pci_bus 0000:00: root bus resource [io 0x03b0-0x03df window][ 0.534392] pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window][ 0.538394] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window][ 0.542393] pci_bus 0000:00: root bus resource [mem 0x000c0000-0x000dffff window][ 0.546392] pci_bus 0000:00: root bus resource [mem 0xe0000000-0xfec2ffff window][ 0.550392] pci_bus 0000:00: root bus resource [mem 0xfee00000-0xffffffff window][ 0.554392] pci_bus 0000:00: root bus resource [bus 00-ff]
所以,我这个设备只有一个主桥,按照如下方式链接的。
分析桥连接情况
先看一个设备
00:01.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Device 148200:01.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 148300:01.3 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 1483
这里   
00:01.0 的ClassCode 为 00 00 06 ,对应是 Host Bridge 设备
00:01.1 和 00:01.3 的Class Code为 00 04 06,对应是 PCI bridge 设备
C 06 Bridge00 Host bridge04 PCI bridge00 Normal decode
- 其次,我们根据 /sys/bus/pci/devices/ 分析了设备的位置,
 
0000:01:00.0 -> ../../../devices/pci0000:00/0000:00:01.1/0000:01:00.00000:03:00.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.00000:03:00.1 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.10000:03:00.2 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.20000:20:00.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:00.00000:20:01.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:01.00000:20:04.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:04.00000:22:00.0 -> ../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:20:01.0/0000:22:00.00000:26:00.0 -> ../../../devices/pci0000:00/0000:00:03.1/0000:26:00.00000:26:00.1 -> ../../../devices/pci0000:00/0000:00:03.1/0000:26:00.10000:27:00.0 -> ../../../devices/pci0000:00/0000:00:07.1/0000:27:00.00000:28:00.0 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.00000:28:00.1 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.10000:28:00.3 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.30000:28:00.4 -> ../../../devices/pci0000:00/0000:00:08.1/0000:28:00.40000:30:00.0 -> ../../../devices/pci0000:00/0000:00:08.2/0000:30:00.00000:31:00.0 -> ../../../devices/pci0000:00/0000:00:08.3/0000:31:00.0
- 最后,根据lspci 查看设备类型,确定设备(先不考虑多功能设备)结构如下:

 
其实通过 /sys/bus/pci/devices/  进行总线分析 是最好用的手段
可以用以下 参考代码 来遍历所有总线及设备:
static void dump_pci_tree(struct pci_bus * bus){struct pci_dev *dev;pr_info("PCI BUS is %d, primary is %d\n", bus->number, bus->primary);list_for_each_entry(dev, &bus->devices, bus_list) {struct pci_bus *b = dev->subordinate;printk("%.2x:%.2x.%.2x: vendor=%x,device=%x\n",dev->bus->number, dev->devfn >> 3,dev->devfn & 7 ,dev->vendor,dev->device);if(b)dump_pci_tree(b);}}list_for_each_entry(bus, &pci_root_buses, node){dump_pci_tree(bus);}
