用QEMU研究Linux內(nèi)核PCI子系統(tǒng)
譯文【51CTO.com快譯】Linux PCI子系統(tǒng)是Linux內(nèi)核中最重要的子系統(tǒng)之一。本文介紹了使用QEMU來仿真不同的PCI/PCIe配置,以幫助研究Linux PCI子系統(tǒng)。這種能力便于Linux管理員或開發(fā)人員研究、調(diào)試和開發(fā)Linux內(nèi)核,因為使用QEMU定制PCI/PCIe配置要容易得多。比如說,結合SeaBIOS源代碼,研究PCI初始化和探測過程會容易得多。此外,與重啟裸機服務器相比,重啟QEMU/KVM虛擬機的速度也快得多。
就本文中的所有示例而言,KVM虛擬機運行Oracle Linux 8,虛擬機內(nèi)核版本為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規(guī)范的任何基礎知識。
PCI橋
這部分演示如何通過PCI-2-PCI橋創(chuàng)建PCI輔助總線。輔助總線通過“pci-bridge”來創(chuàng)建。
- qemu-system-x86_64 -machine pc,accel=kvm -vnc :8 -smp 4 -m 4096M \
- -net nic -net user,hostfwd=tcp::5028-:22 \
- -hda ol8.qcow2 -serial stdio \
- -device pci-bridge,id=bridge0,chassis_nr=1 \
- -device virtio-scsi-pci,id=scsi0,bus=bridge0,addr=0x3 \
- -device pci-bridge,id=bridge1,chassis_nr=2 \
- -device virtio-scsi-pci,id=scsi1,bus=bridge1,addr=0x3 \
- -device virtio-scsi-pci,id=scsi2,bus=bridge1,addr=0x4
上述QEMU命令行創(chuàng)建兩條PCI輔助總線。一條輔助總線(01:00.0)有一個virtio-scsi-pci HBA(01:03.0),第二條輔助總線(02:00.0)有兩個virtio-scsi-pci HBA(02:03.0和02:04.0)。
- [root@vm ~]# lspci
- 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
- 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
- 00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
- 00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
- 00:02.0 VGA compatible controller: Device 1234:1111 (rev 02)
- 00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
- 00:04.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge
- 00:05.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge
- 01:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
- 02:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
- 02:04.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
下列l(wèi)spci輸出和數(shù)字描述了該示例的PCI總線拓撲結構。
- [root@vm ~]# lspci -t
- [0000:00]-+-00.0
- +-01.0
- +-01.1
- +-01.3
- +-02.0
- +-03.0
- +-04.0-[01]----03.0
- \-05.0-[02]--+-03.0
- \-04.0
圖1
PCI根總線
這部分演示如何通過“輕量級”PXB(PCI擴展橋)主機橋創(chuàng)建額外的PCI根總線。它是QEMU命令行中的“pxb”。它僅針對i440fx實現(xiàn),只可以放在總線0上。
- qemu-system-x86_64 -machine pc,accel=kvm -vnc :8 -smp 4 -m 4096M \
- -net nic -net user,hostfwd=tcp::5028-:22 \
- -hda ol8.qcow2 -serial stdio \
- -device pxb,id=bridge1,bus=pci.0,bus_nr=3 \
- -device virtio-scsi-pci,bus=bridge1,addr=0x3 \
- -device pxb,id=bridge2,bus=pci.0,bus_nr=8 \
- -device virtio-scsi-pci,bus=bridge2,addr=0x3 \
- -device virtio-scsi-pci,bus=bridge2,addr=0x4
上述QEMU命令行創(chuàng)建兩條額外的PCI 根總線。第一條根總線(04:00.0)有一個virtio-scsi-pci HBA(04:03.0),第二條根總線(09:00.0)有二個virtio-scsi-pci HBA(09:03.0和09:04.0)。
- [root@vm ~]# lspci
- 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
- 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
- 00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
- 00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
- 00:02.0 VGA compatible controller: Device 1234:1111 (rev 02)
- 00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
- 00:04.0 Host bridge: Red Hat, Inc. QEMU PCI Expander bridge
- 00:05.0 Host bridge: Red Hat, Inc. QEMU PCI Expander bridge
- 03:00.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge
- 04:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
- 08:00.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge
- 09:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
- 09:04.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
下列l(wèi)spci輸出和數(shù)字描述了該示例的PCI總線拓撲結構。
- [root@vm ~]# lspci -t
- +-[0000:08]---00.0-[09]--+-03.0
- | \-04.0
- +-[0000:03]---00.0-[04]----03.0
- \-[0000:00]-+-00.0
- +-01.0
- +-01.1
- +-01.3
- +-02.0
- +-03.0
- +-04.0
- \-05.0
圖2
PCIe根聯(lián)合體
這部分演示如何通過額外的根聯(lián)合體(Root Complex)創(chuàng)建額外的PCIe根總線。據(jù)QEMU源代碼顯示,PCIe特性只由x86架構上的“q35”機器類型和AArch64上的“virt”機器類型所支持。根聯(lián)合體通過在QEMU命令行上使用“pxb-pcie”來創(chuàng)建。
- qemu-system-x86_64 -machine q35,accel=kvm -vnc :8 -smp 4 -m 4096M \
- -net nic -net user,hostfwd=tcp::5028-:22 \
- -hda ol8.qcow2 -serial stdio \
- -device pxb-pcie,id=pcie.1,bus_nr=2,bus=pcie.0 \
- -device ioh3420,id=pcie_port1,bus=pcie.1,chassis=1 \
- -device virtio-scsi-pci,bus=pcie_port1 \
- -device ioh3420,id=pcie_port2,bus=pcie.1,chassis=2 \
- -device virtio-scsi-pci,bus=pcie_port2 \
- -device pxb-pcie,id=pcie.2,bus_nr=8,bus=pcie.0 \
- -device ioh3420,id=pcie_port3,bus=pcie.2,chassis=3 \
- -device virtio-scsi-pci,bus=pcie_port3
上述QEMU命令行創(chuàng)建兩個額外的PCIe根聯(lián)合體。第一個根聯(lián)合體有一個virtio-scsi-pci HBA(09:00.0),第二個根聯(lián)合體有兩個virtio-scsi-pci HBA(03:00.0和04:00.0)。
- [root@vm ~]# lspci
- 00:00.0 Host bridge: Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller
- 00:01.0 VGA compatible controller: Device 1234:1111 (rev 02)
- 00:02.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
- 00:03.0 Host bridge: Red Hat, Inc. QEMU PCIe Expander bridge
- 00:04.0 Host bridge: Red Hat, Inc. QEMU PCIe Expander bridge
- 00:1f.0 ISA bridge: Intel Corporation 82801IB (ICH9) LPC Interface Controller (rev 02)
- 00:1f.2 SATA controller: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (rev 02)
- 00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 02)
- 02:00.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
- 02:01.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
- 03:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01)
- 04:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01)
- 08:00.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
- 09:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01)
下列l(wèi)spci輸出和數(shù)字描述了該示例的PCIe拓撲結構。
- [root@vm ~]# lspci -t
- -+-[0000:08]---00.0-[09]----00.0
- +-[0000:02]-+-00.0-[03]----00.0
- | \-01.0-[04]----00.0
- \-[0000:00]-+-00.0
- +-01.0
- +-02.0
- +-03.0
- +-04.0
- +-1f.0
- +-1f.2
- \-1f.3
圖3
PCI交換器
這部分演示了如何創(chuàng)建PCIe交換器。
- qemu-system-x86_64 -machine q35,accel=kvm -vnc :8 -smp 4 -m 4096M \
- -net nic -net user,hostfwd=tcp::5028-:22 \
- -hda ol8.qcow2 -serial stdio \
- -device ioh3420,id=root_port1,bus=pcie.0 \
- -device x3130-upstream,id=upstream1,bus=root_port1 \
- -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 virtio-scsi-pci,bus=downstream2
上述QEMU命令行創(chuàng)建了一個PCIe交換器,它連接有兩個virtio-scsi-pci HBA。上游端口連接至根總線,而每個下游端口連接至virtio-scsi-pci HBA(03:00.0和04:00.0)。
- [root@vm ~]# lspci
- 00:00.0 Host bridge: Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller
- 00:01.0 VGA compatible controller: Device 1234:1111 (rev 02)
- 00:02.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
- 00:03.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
- 00:1f.0 ISA bridge: Intel Corporation 82801IB (ICH9) LPC Interface Controller (rev 02)
- 00:1f.2 SATA controller: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (rev 02)
- 00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 02)
- 01:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Upstream) (rev 02)
- 02:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01)
- 02:01.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01)
- 03:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01)
- 04:00.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI (rev 01)
下列l(wèi)spci輸出和數(shù)字描述了該示例的PCIe拓撲結構。
- [root@vm ~]# lspci -t
- -[0000:00]-+-00.0
- +-01.0
- +-02.0
- +-03.0-[01-04]----00.0-[02-04]--+-00.0-[03]----00.0
- | \-01.0-[04]----00.0
- +-1f.0
- +-1f.2
- \-1f.3
圖4
IOMMU
現(xiàn)在,IOMMU始終被裸機所使用。QEMU能夠仿真IOMMU,幫助開發(fā)人員調(diào)試和研究Linux內(nèi)核IOMMU相關源代碼以及DMA重映射和中斷重映射的工作原理。
下列QEMU命令行演示了如何為虛擬機創(chuàng)建英特爾IOMMU(啟用中斷重映射)。除了QEMU命令行外,還應該將“intel_iommu=on”添加到虛擬機Linux內(nèi)核命令行的末尾。
- qemu-system-x86_64 -machine q35,accel=kvm,kernel-irqchip=split -vnc :8 -smp 4 -m 4096M \
- -net nic -net user,hostfwd=tcp::5028-:22 \
- -hda ol8.qcow2 -serial stdio \
- -device nvme,drive=nvme0,serial=deadbeaf1,max_ioqpairs=4 \
- -drive file=disk1.qcow2,if=none,id=nvme0 \
- -device intel-iommu,intremap=on
據(jù)虛擬機系統(tǒng)日志顯示,IOMMU可用,并被Linux內(nèi)核啟用。
- [root@vm ~]# dmesg | egrep "iommu|IOMMU"
- ... ...
- [ 0.019828] DMAR: IOMMU enabled
- [ 0.203209] DMAR-IR: IOAPIC id 0 under DRHD base 0xfed90000 IOMMU 0
- [ 0.628348] iommu: Default domain type: Passthrough
- [ 1.078994] pci 0000:00:00.0: Adding to iommu group 0
- [ 1.079892] pci 0000:00:01.0: Adding to iommu group 1
- [ 1.080775] pci 0000:00:02.0: Adding to iommu group 2
- [ 1.081654] pci 0000:00:03.0: Adding to iommu group 3
- [ 1.082545] pci 0000:00:1f.0: Adding to iommu group 4
- [ 1.083432] pci 0000:00:1f.2: Adding to iommu group 4
- [ 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】