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.
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 \