PCI-Device-Passthrough

Industrie-PCs mit IOMMU-Virtualisierungsfunktionen erlauben das explizite Zuweisen von physischen PCI-Geräten an eine virtuelle Maschine (siehe Tabelle: Geräteunterstützung für TwinCAT/BSD Hypervisor, Device- und GPU-Passthrough.). PCI-Geräte wie die GPU, Netzwerkschnittstellen oder USB-Controller können als passthru Geräte explizit einer virtuellen Maschine zugewiesen werden.

Um ein PCI-Gerät einer virtuellen Maschine zuzuweisen, wird zunächst dessen PCI-Adresse benötigt. Mit dem Kommando pciconf -l werden alle PCI-Geräte sowie ihre Adressen gelistet.

$ pciconf -l
...
vgapci0@pci0:0:2:0: class=0x030000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x3e92 subvendor=0x8086 subdevice=0x2212
xhci0@pci0:0:20:0: class=0x0c0330 rev=0x10 hdr=0x00 vendor=0x8086 device=0xa36d subvendor=0x8086 subdevice=0x7270
igb0@pci0:1:0:0: class=0x020000 rev=0x03 hdr=0x00 vendor=0x8086 device=0x1533 subvendor=0x8086 subdevice=0x1533
...

Im folgenden Beispiel sollen die drei gelisteten Geräte einer virtuellen Maschine zugewiesen werden.

PCI-Device-Passthrough 1:
Konfiguration einer VM-Instanz mit PCI-Device-Passthrough.

Gerät

Beschreibung

Adresse

vgapci0@pci0:0:2:0

GPU

pci0:0:2:0

igb2@pci1:0:0:0

Ethernet Controller

pci1:0:0:0

xhci1@pci0:20:0:0

USB-Controller

pci0:20:0:0

Um die Geräte vom TwinCAT/BSD-Host zu isolieren, werden Geräten mit devctl der ppt (PCI PassThrough) Treiber zugewiesen.

doas devctl set driver -f pci0:0:2:0 ppt
doas devctl set driver -f pci0:0:20:0 ppt
doas devctl set driver -f pci0:1:0:0 ppt

Um die Treiber bereits beim Systemboot zu setzen, können die PCI-Adressen als pptdevs der Datei /boot/loader.conf hinzugefügt werden:

pptdevs="1/0/0 0/2/0 0/20/0"

Eine erneute Ausgabe von pciconf -l zeigt nun, dass die ppt Treiber den Geräten zugewiesen wurden:

$ pciconf -l
...
ppt0@pci0:0:2:0: class=0x030000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x3e92 subvendor=0x8086 subdevice=0x2212
ppt1@pci0:0:20:0: class=0x0c0330 rev=0x10 hdr=0x00 vendor=0x8086 device=0xa36d subvendor=0x8086 subdevice=0x7270
ppt2@pci0:1:0:0: class=0x020000 rev=0x03 hdr=0x00 vendor=0x8086 device=0x1533 subvendor=0x8086 subdevice=0x1533
...

Die PCI-Geräte können nun bhyve mit dem Parameter -s [slot],passthru,[slot/bus/function] übergeben werden. Die Werte für [slot/bus/function] beziehen sich dabei auf die PCI-Adressen der pciconf -l Ausgabe. Da Passthrough-Geräte fixe Speicheradressen verwenden, muss byhve zusätzlich das Flag -S als Parameter übergeben werden, um Memory-Swapping für den Prozess zu deaktivieren.

Der bhyve Aufruf mit zugewiesener on-board GPU, Ethernet- und USB-Controller ergibt sich für das Beispiel wie folgt:

doas bhyve \
-c sockets=1,cores=2,threads=1 \
-m 4G \
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd,fwcfg=qemu \
-s 0:0,hostbridge \
-s 2:0,passthru,0/2/0 \
-s 3:0,passthru,0/20/0 \
-s 10:0,nvme,/vms/samplevm/disk0.img \
-s 20:0,passthru,1/0/0 \
-s 31:0,lpc \
-A -H -P -S \
samplevm

Erweiterte Parameter für das Durchreichen der integrierten GPU

Das Durchreichen der integrierten GPU auf unterstützten IPCs benötigt erweiterte bhyve-Parameter, damit die EFI-Firmware BHYVE_BHF_UEFI.fd die integrierte Grafikkarte während des Boot-Vorgangs der virtuellen Maschine korrekt initialisieren und dem Gast-Betriebssystem zur Verfügung stellen kann.

doas bhyve \
-c sockets=1,cores=2,threads=1 \
-m 4G \
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd,fwcfg=qemu \
-s 0:0,hostbridge \
-s 2:0,passthru,0/2/0,rom=/vms/samplevm/gop.rom \
-s 3:0,passthru,0/20/0 \
-s 10:0,nvme,/vms/samplevm/disk0.img \
-s 20:0,passthru,1/0/0 \
-s 31:0,lpc \
-o pci.0.31.0.pcireg.vendor=host \
-o pci.0.31.0.pcireg.device=host \
-o pci.0.31.0.pcireg.revid=host \
-o pci.0.31.0.pcireg.subvendor=host \
-o pci.0.31.0.pcireg.subdevice=host
\
-A -H -P -S \
samplevm

Der passthru Parameter für die integrierte Grafikkarte ( -s 2:0,passthru,0/2/0 ) wird um ,rom=/vms/samplevm/gop.rom erweitert.
Die Datei gop.rom wird für die Initialisierung der Grafikkarte durch das EFI benötigt und kann mit folgendem Befehlt erstellt werden:

doas gop-dump /vms/samplevm/gop.rom

Zusätzlich müssen, wie oben dargestellt, die PCI-Register der emulierten LPC-Bridge beim bhyve Aufruf auf den Wert host gesetzt werden:

-o pci.0.31.0.pcireg.vendor=host \
-o pci.0.31.0.pcireg.device=host \
-o pci.0.31.0.pcireg.revid=host \
-o pci.0.31.0.pcireg.subvendor=host \
-o pci.0.31.0.pcireg.subdevice=host \