PCI以及PCIE设备非常普遍,其驱动也是内核中非常重要的一部分,受到网友的启发,借助QEMU一次性把PCI/PCIE的拓扑结构给说透(尽量)。
为了简单,这里使用virtio-scsi-pci HBA (host bus adapter)作为例子,分别来探究PCI和PCIE两种不同类型的总线。
PCI
先来PCI3.0文档里的拓扑图
PCI Root Bus (PXB, PCI Expander Bridge)
如上图所示,左上角的Processor/cache/DRAM 都经过一个Bridge,链接在了PCI 总线上。(忽略掉Aduio和Motion Video两个设备),图的左下的Lan 和SCSI两个设备直接连在了PCI总线上。
下面就利用QEMU模拟这两种PCI设备的场景。
1 | qemu-system-x86_64 \ |
说明:
- 箭头1,是把HBA直接接在了PCI bus上,并且地址是0x4。
- 箭头2,是接了一个PXB(PCI Expander Bridge)到PCI bus上,实际上是增加了PCI bus,配置bus号为0x3,地址是0x5。
- 箭头3,跟2类似,只不过下面再接两个HBA,bus号是0x8。
- 箭头4,接一个bridge到PCIbus上面,bridge的地址是0x14; bridge不会新增Bus号!同时在其下添加一个HBA,地址配置为0x6
- 箭头5,与4类似,区别就是在下面接两个HBA。
对应的拓扑结构如下所示:
1 | root@u2010-mini:~# lspci -tvnn |
1 | pci.0 bus |
PCIE
先来PCIE5.0文档里的拓扑结构图。
PCIE分两个小结来探讨。
PCIE root complex / PCIE-PCI bridge / PCIE / PCI
1 | qemu-system-x86_64 \ |
说明:
- 箭头3,是把HBA直接接在了PCIE bus上,并且地址是0x3。
- 箭头3,是接了一个PXB(PCI Expander Bridge)到PCIE bus上,增加了PCIE bus,配置bus号为0x3,地址是0x4。
- 箭头3,然后再在pxb-pcie上接一个IOHUB,并且配置地址是0x6,然后再把HBA接再HUB上。相比PCI bug多了一个HUB,是因为pxb-pcie不可以直接接PCIE设备。
- 箭头4,接了一个PCIE-PCI的bridge,下面可以在接多个pci设备。
1 | # lspci -tvnn |
1 | pci.0 bus |
PCIE SWITCH
对于switch,这里特别的拎出来说下。PCIE5 spec文档的图是这样的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20qemu-system-x86_64 \
-m 2048 -smp 1 \
-enable-kvm \
-cpu max \
-vga none -nodefaults -nographic \
-serial mon:stdio \
-hda /home/works/kvm/ubuntu20.10_mini.img \
-bios ovmf/OVMF_CODE.fd \
-append "root=/dev/sda3 nokaslr console=ttyS0" \
-kernel /home/works/linux-stable/arch/x86/boot/bzImage \
-net nic -net user,hostfwd=tcp::5028-:22 \
-machine q35,kernel-irqchip=split \
-device intel-iommu,intremap=on \
1-> -device ioh3420,id=root_port1,bus=pcie.0 \
2-> -device x3130-upstream,id=upstream1,bus=root_port1 \
3-> -device xio3130-downstream,id=downstream1,bus=upstream1,chassis=9 \
-device virtio-scsi-pci,bus=downstream1 \
-device xio3130-downstream,id=downstream2,bus=upstream1,chassis=10 \
-device e1000e,bus=downstream2 \
-device virtio-scsi-pci,bus=downstream2 \
说明:
- 箭头1,创建一个PCI Express Root Ports (ioh3420)
- 箭头2,与PCI设备不同,PCIE swith其实是两个bus上下连接起来的,upstream 和downstream。
然后在downstream的下面,接PCI/PCIE设备. switch的upstream,其实相当于一个pci bus. - 箭头3,switch的downstream,也相当于一个pci bus。再在downstream的下面,挂设备,既有PCI设备(HBA)又有PCIE设备(e1000e)。
1 | # lspci -tvnn |
1 | pci.0 bus |
参考文档
NCB-PCI_Express_Base_5.0r1.0-2019-05-22.pdf
PCI_LB3.0-2-6-04.pdf
qemu-6.1.0/docs/pcie.txt
A study of the Linux kernel PCI subsystem with QEMU