用QEMU研究Linux内核PCI子系统

译文
系统 Linux
Oracle Linux内核工程师Dongli Zhang介绍了如何利用QEMU研究Linux内核PCI子系统。

[[409636]]

【51CTO.com快译】Linux PCI子系统是Linux内核中最重要的子系统之一。本文介绍了使用QEMU来仿真不同的PCI/PCIe配置,以帮助研究Linux PCI子系统。这种能力便于Linux管理员或开发人员研究、调试和开发Linux内核,因为使用QEMU定制PCI/PCIe配置要容易得多。比如说,结合SeaBIOS源代码,研究PCI初始化和探测过程会容易得多。此外,与重启裸机服务器相比,重启QEMU/KVM虚拟机的速度也快得多。

就本文中的所有示例而言,KVM虚拟机运行Oracle Linux 8,虚拟机内核版本为5.10.0,QEMU版本为 5.2.0。

所有示例都将启动盘(ol8.qcow2)作为默认IDE来运行。由于本文的目的是研究PCI/PCIe,我们以virtio-scsi-pci HBA为例,不会将任何SCSI LUN连接到HBA。参阅之前的这篇博文,即可了解如何将SCSI LUN连接到 virtio-scsi-pci HBA。

文章重点介绍使用QEMU和PCI/PCIe,不涉及有关PCI/PCIe规范的任何基础知识。

PCI桥

这部分演示如何通过PCI-2-PCI桥创建PCI辅助总线。辅助总线通过“pci-bridge”来创建。

  1. qemu-system-x86_64 -machine pc,accel=kvm -vnc :8 -smp 4 -m 4096M \ 
  2. -net nic -net user,hostfwd=tcp::5028-:22 \ 
  3. -hda ol8.qcow2 -serial stdio \ 
  4. -device pci-bridge,id=bridge0,chassis_nr=1 \ 
  5. -device virtio-scsi-pci,id=scsi0,bus=bridge0,addr=0x3 \ 
  6. -device pci-bridge,id=bridge1,chassis_nr=2 \ 
  7. -device virtio-scsi-pci,id=scsi1,bus=bridge1,addr=0x3 \ 
  8. -device virtio-scsi-pci,id=scsi2,bus=bridge1,addr=0x4 

上述QEMU命令行创建两条PCI辅助总线。一条辅助总线(01:00.0)有一个virtio-scsi-pci HBA(01:03.0),第二条辅助总线(02:00.0)有两个virtio-scsi-pci HBA(02:03.0和02:04.0)。

  1. [root@vm ~]# lspci 
  2. 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02) 
  3. 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II] 
  4. 00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II] 
  5. 00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03) 
  6. 00:02.0 VGA compatible controller: Device 1234:1111 (rev 02) 
  7. 00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03) 
  8. 00:04.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge 
  9. 00:05.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge 
  10. 01:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 
  11. 02:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 
  12. 02:04.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 

下列lspci输出和数字描述了该示例的PCI总线拓扑结构。

  1. [root@vm ~]# lspci -t 
  2. [0000:00]-+-00.0 
  3.           +-01.0 
  4.           +-01.1 
  5.           +-01.3 
  6.           +-02.0 
  7.           +-03.0 
  8.           +-04.0-[01]----03.0 
  9.           \-05.0-[02]--+-03.0 
  10.                        \-04.0 

图1

PCI根总线

这部分演示如何通过“轻量级”PXB(PCI扩展桥)主机桥创建额外的PCI根总线。它是QEMU命令行中的“pxb”。它仅针对i440fx实现,只可以放在总线0上。

  1. qemu-system-x86_64 -machine pc,accel=kvm -vnc :8 -smp 4 -m 4096M \ 
  2. -net nic -net user,hostfwd=tcp::5028-:22 \ 
  3. -hda ol8.qcow2 -serial stdio \ 
  4. -device pxb,id=bridge1,bus=pci.0,bus_nr=3 \ 
  5. -device virtio-scsi-pci,bus=bridge1,addr=0x3 \ 
  6. -device pxb,id=bridge2,bus=pci.0,bus_nr=8 \ 
  7. -device virtio-scsi-pci,bus=bridge2,addr=0x3 \ 
  8. -device virtio-scsi-pci,bus=bridge2,addr=0x4 

上述QEMU命令行创建两条额外的PCI 根总线。第一条根总线(04:00.0)有一个virtio-scsi-pci HBA(04:03.0),第二条根总线(09:00.0)有二个virtio-scsi-pci HBA(09:03.0和09:04.0)。

  1. [root@vm ~]# lspci 
  2. 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02) 
  3. 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II] 
  4. 00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II] 
  5. 00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03) 
  6. 00:02.0 VGA compatible controller: Device 1234:1111 (rev 02) 
  7. 00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03) 
  8. 00:04.0 Host bridge: Red Hat, Inc. QEMU PCI Expander bridge 
  9. 00:05.0 Host bridge: Red Hat, Inc. QEMU PCI Expander bridge 
  10. 03:00.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge 
  11. 04:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 
  12. 08:00.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge 
  13. 09:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 
  14. 09:04.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 

下列lspci输出和数字描述了该示例的PCI总线拓扑结构。

  1. [root@vm ~]# lspci -t 
  2. +-[0000:08]---00.0-[09]--+-03.0 
  3. |                        \-04.0 
  4. +-[0000:03]---00.0-[04]----03.0 
  5. \-[0000:00]-+-00.0 
  6.             +-01.0 
  7.             +-01.1 
  8.             +-01.3 
  9.             +-02.0 
  10.             +-03.0 
  11.             +-04.0 
  12.             \-05.0 

图2

PCIe根联合体

这部分演示如何通过额外的根联合体(Root Complex)创建额外的PCIe根总线。据QEMU源代码显示,PCIe特性只由x86架构上的“q35”机器类型和AArch64上的“virt”机器类型所支持。根联合体通过在QEMU命令行上使用“pxb-pcie”来创建。

  1. qemu-system-x86_64 -machine q35,accel=kvm -vnc :8 -smp 4 -m 4096M \ 
  2. -net nic -net user,hostfwd=tcp::5028-:22 \ 
  3. -hda ol8.qcow2 -serial stdio \ 
  4. -device pxb-pcie,id=pcie.1,bus_nr=2,bus=pcie.0 \ 
  5. -device ioh3420,id=pcie_port1,bus=pcie.1,chassis=1 \ 
  6. -device virtio-scsi-pci,bus=pcie_port1 \ 
  7. -device ioh3420,id=pcie_port2,bus=pcie.1,chassis=2 \ 
  8. -device virtio-scsi-pci,bus=pcie_port2 \ 
  9. -device pxb-pcie,id=pcie.2,bus_nr=8,bus=pcie.0 \ 
  10. -device ioh3420,id=pcie_port3,bus=pcie.2,chassis=3 \ 
  11. -device virtio-scsi-pci,bus=pcie_port3 

上述QEMU命令行创建两个额外的PCIe根联合体。第一个根联合体有一个virtio-scsi-pci HBA(09:00.0),第二个根联合体有两个virtio-scsi-pci HBA(03:00.0和04:00.0)。

  1. [root@vm ~]# lspci 
  2. 00:00.0 Host bridge: Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller 
  3. 00:01.0 VGA compatible controller: Device 1234:1111 (rev 02) 
  4. 00:02.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection 
  5. 00:03.0 Host bridge: Red Hat, Inc. QEMU PCIe Expander bridge 
  6. 00:04.0 Host bridge: Red Hat, Inc. QEMU PCIe Expander bridge 
  7. 00:1f.0 ISA bridge: Intel Corporation 82801IB (ICH9) LPC Interface Controller (rev 02) 
  8. 00:1f.2 SATA controller: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (rev 02) 
  9. 00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 02) 
  10. 02:00.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02) 
  11. 02:01.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02) 
  12. 03:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01) 
  13. 04:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01) 
  14. 08:00.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02) 
  15. 09:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01) 

下列lspci输出和数字描述了该示例的PCIe拓扑结构。

  1. [root@vm ~]# lspci -t 
  2. -+-[0000:08]---00.0-[09]----00.0 
  3.  +-[0000:02]-+-00.0-[03]----00.0 
  4.  |           \-01.0-[04]----00.0 
  5.  \-[0000:00]-+-00.0 
  6.              +-01.0 
  7.              +-02.0 
  8.              +-03.0 
  9.              +-04.0 
  10.              +-1f.0 
  11.              +-1f.2 
  12.              \-1f.3 

图3

PCI交换器

这部分演示了如何创建PCIe交换器。

  1. qemu-system-x86_64 -machine q35,accel=kvm -vnc :8 -smp 4 -m 4096M \ 
  2. -net nic -net user,hostfwd=tcp::5028-:22 \ 
  3. -hda ol8.qcow2 -serial stdio \ 
  4. -device ioh3420,id=root_port1,bus=pcie.0 \ 
  5. -device x3130-upstream,id=upstream1,bus=root_port1 \ 
  6. -device xio3130-downstream,id=downstream1,bus=upstream1,chassis=9 \ 
  7. -device virtio-scsi-pci,bus=downstream1 \ 
  8. -device xio3130-downstream,id=downstream2,bus=upstream1,chassis=10 \ 
  9. -device virtio-scsi-pci,bus=downstream2 

上述QEMU命令行创建了一个PCIe交换器,它连接有两个virtio-scsi-pci HBA。上游端口连接至根总线,而每个下游端口连接至virtio-scsi-pci HBA(03:00.0和04:00.0)。

  1.  [root@vm ~]# lspci 
  2. 00:00.0 Host bridge: Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller 
  3. 00:01.0 VGA compatible controller: Device 1234:1111 (rev 02) 
  4. 00:02.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection 
  5. 00:03.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02) 
  6. 00:1f.0 ISA bridge: Intel Corporation 82801IB (ICH9) LPC Interface Controller (rev 02) 
  7. 00:1f.2 SATA controller: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (rev 02) 
  8. 00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 02) 
  9. 01:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Upstream) (rev 02) 
  10. 02:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01) 
  11. 02:01.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01) 
  12. 03:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01) 
  13. 04:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01) 

下列lspci输出和数字描述了该示例的PCIe拓扑结构。

  1. [root@vm ~]# lspci -t 
  2. -[0000:00]-+-00.0 
  3.            +-01.0 
  4.            +-02.0 
  5.            +-03.0-[01-04]----00.0-[02-04]--+-00.0-[03]----00.0 
  6.            |                               \-01.0-[04]----00.0 
  7.            +-1f.0 
  8.            +-1f.2 
  9.            \-1f.3 

图4

IOMMU

现在,IOMMU始终被裸机所使用。QEMU能够仿真IOMMU,帮助开发人员调试和研究Linux内核IOMMU相关源代码以及DMA重映射和中断重映射的工作原理。

下列QEMU命令行演示了如何为虚拟机创建英特尔IOMMU(启用中断重映射)。除了QEMU命令行外,还应该将“intel_iommu=on”添加到虚拟机Linux内核命令行的末尾。

  1. qemu-system-x86_64 -machine q35,accel=kvm,kernel-irqchip=split -vnc :8 -smp 4 -m 4096M \ 
  2. -net nic -net user,hostfwd=tcp::5028-:22 \ 
  3. -hda ol8.qcow2 -serial stdio \ 
  4. -device nvme,drive=nvme0,serial=deadbeaf1,max_ioqpairs=4 \ 
  5. -drive file=disk1.qcow2,if=none,id=nvme0 \ 
  6. -device intel-iommu,intremap=on 

据虚拟机系统日志显示,IOMMU可用,并被Linux内核启用。

  1.  [root@vm ~]# dmesg | egrep "iommu|IOMMU" 
  2. ... ... 
  3. [    0.019828] DMAR: IOMMU enabled 
  4. [    0.203209] DMAR-IR: IOAPIC id 0 under DRHD base  0xfed90000 IOMMU 0 
  5. [    0.628348] iommu: Default domain type: Passthrough 
  6. [    1.078994] pci 0000:00:00.0: Adding to iommu group 0 
  7. [    1.079892] pci 0000:00:01.0: Adding to iommu group 1 
  8. [    1.080775] pci 0000:00:02.0: Adding to iommu group 2 
  9. [    1.081654] pci 0000:00:03.0: Adding to iommu group 3 
  10. [    1.082545] pci 0000:00:1f.0: Adding to iommu group 4 
  11. [    1.083432] pci 0000:00:1f.2: Adding to iommu group 4 
  12. [    1.084315] pci 0000:00:1f.3: Adding to iommu group 4 

原文标题:A study of the Linux kernel PCI subsystem with QEMU,作者:Dongli Zhang

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

 

责任编辑:华轩 来源: 51CTO
相关推荐

2016-07-22 10:50:56

Linux内核无线子系统

2021-12-15 10:02:25

鸿蒙HarmonyOS应用

2009-10-12 12:46:55

Linux内核SCSI IO

2015-10-19 17:36:19

MOST内核Linux

2013-11-25 17:39:17

Linux内核PCIACPI

2019-07-15 08:30:06

Linux 系统 数据

2013-12-18 11:14:57

Linux内核Linux Kerne

2021-04-06 11:18:47

LinuxWWAN子系统驱动

2021-12-08 08:41:31

Linux 中断子系统Linux 系统

2021-07-22 08:03:08

Windows 操作系统Linux

2021-08-31 11:53:38

Linux inputLinux 系统

2016-10-17 08:49:15

WindowsLinuxArch Linux

2021-08-10 11:30:30

Linux代码中断控制器

2021-08-03 15:10:26

Linux代码驱动

2021-06-07 08:13:11

LinuxIDLE 子系统

2022-01-16 07:41:46

Windows 11操作系统微软

2022-11-27 11:00:15

2010-12-13 13:43:16

PCI DSS数据泄漏

2021-09-27 09:52:41

FacebookBOLTLinux

2015-11-10 16:55:00

性能IO子系统Linux
点赞
收藏

51CTO技术栈公众号