Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
FreeBSD - Bhyve
Bhyve ist ein Hypervisor, auf dem Gastbetriebssysteme in einer virtuellen Maschine ausgeführt werden.
Bhyve installieren
das Virtualisierungsmodul laden:
> kldload vmm > echo 'vmm_load="YES"' >> /boot/loader.conf
die Netzwerkanbindung vorbereiten:
> ifconfig tap0 create > sysctl net.link.tap.up_on_open=1 net.link.tap.up_on_open: 0 -> 1 > ifconfig bridge0 create > ifconfig bridge0 addm igb0 addm tap0 > ifconfig bridge0 up
Konfiguration persistent machen, damit sie nach einem Reboot wieder vorhanden ist:
> echo "net.link.tap.up_on_open=1" >> /etc/sysctl.conf > echo 'cloned_interfaces="bridge0 tap0"' >> /etc/rc.conf > echo 'ifconfig_bridge0="addm igb0 addm tap0"' >> /etc/rc.conf > echo 'kld_list="vmm nmdm"' >> /etc/rc.conf
für eine 2. VM bräuchte man dann ein weiteres TAP:
> ifconfig tap1 create > ifconfig bridge0 addm tap1
und diese beiden Zeilen müssten dann in der geändert werden:
> vi /etc/rc.conf ... cloned_interfaces="bridge0 tap0 tap1" ifconfig_bridge0="addm igb0 addm tap0 addm tap1" ...
FreeBSD als Gast in der VM starten
eine virtuelle Festplatte erstellen:
> truncate -s 16G freebsd.img
FreeBSD 10.3 in der VM installieren:
> sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M -t tap0 -d freebsd.img -i -I FreeBSD-10.3-RELEASE-amd64-bootonly.iso guestname
die VM von ihrer virtuellen Platte starten:
> sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d freebsd.img guestname
Bhyve-Netzwerkkonfiguration
-
- NAT - VM und Host gehen über die selbe Netzwerkkarte und der selben IP ins Netz
- Bridged networking - VM und Host gehen über die selbe Netzwerkkarte aber unterschiedlichen IPs ins Netz
bhyve -c 2 -m 4G -w -H -s 0,hostbridge -s 3,ahci-cd,/home/novel/FreeBSD-11.0-CURRENT-amd64-20160217-r295683-disc1.iso -s 5,virtio-net,tap1 -s 29,fbuf,tcp=0.0.0.0:5900,w=800,h=600,wait -s 30,xhci,tablet -s 31,lpc -l com1,stdio -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd vm0- Die IP-Adresse wird in der VM statisch konfiguriert.
- NIC Passthrough - eine Netzwerkkarte alleine nur für die VM
bhyve -c 2 -m 1G -w -H -S -s 0,hostbridge -s 4,ahci-hd,/home/novel/img/uefi_fbsd.raw -s 6,passthru,3/0/0 -s 29,fbuf,tcp=0.0.0.0:5900,w=800,h=600,wait -s 30,xhci,tablet -s 31,lpc -l com1,stdio -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd vm0
Bridged networking - VM und Host gehen über die selbe Netzwerkkarte aber unterschiedlichen IPs ins Netz
> pkg install sysutils/grub2-bhyve
eine virtuelle Festplatte erstellen:
> truncate -s 20G linux.img
Linux als Gast in der VM installieren
Map-Datei für den Grub anlegen:
> vi device.map (hd0) ./linux.img (cd0) ./buntu-20.04-legacy-server-amd64.iso
Grub läd den Linux-Kernel vom Installations-ISO-Image:
> grub-bhyve -m device.map -r cd0 -M 4G linuxguest
VM starten:
> bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -s 4:0,ahci-cd,./buntu-20.04-legacy-server-amd64.iso -l com1,stdio -c 4 -m 4G linuxguest > bhyvectl --destroy --vm=linuxguest
in der VM installiertes Linux starten
Map-Datei für den Grub anpassen:
> vi device.map (hd0) ./linux.img
Grub läd den Linux-Kernel von der virtuellen Festplatte:
> grub-bhyve -m device.map -r hd0,msdos1 -M 4G linuxguest
VM starten:
> bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -l com1,stdio -c 4 -m 4G linuxguest > bhyvectl --destroy --vm=linuxguest
Konsolen in der virtuellen Maschine
> kldload nmdm > bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -l com1,/dev/nmdm0A -c 4 -m 4G linuxguest > cu -l /dev/nmdm0B Connected Ubuntu 13.10 handbook ttyS0 handbook login:
Virtuelle Maschinen verwalten
> ls -al /dev/vmm total 1 dr-xr-xr-x 2 root wheel 512 Mar 17 12:19 ./ dr-xr-xr-x 14 root wheel 512 Mar 17 06:38 ../ crw------- 1 root wheel 0x1a2 Mar 17 12:20 guestname crw------- 1 root wheel 0x19f Mar 17 12:19 linuxguest crw------- 1 root wheel 0x1a1 Mar 17 12:19 otherguest
> bhyvectl --destroy --vm=guestname
vereinfachen per Skript am Beispiel einer Minecraft-VM
Das Host-System heißt in diesem Beispiel "server", die VM hat die IP "192.168.1.250" und den Namen "minecraft". Auf dem Host-System tun wir fast alles als Benutzer "fritz" und in der VM als "root".
Die VM sollte derart vorbereitet sein, dass "fritz" sich passwortlos per ssh root@192.168.1.250 einloggen kann.
- dazu muss eine statische Netzwerkkonfiguration im VM-OS konfiguriert sein
- weiterhin muss der Benutzer "fritz" einen SSH-Schlüssel besitzen
- und der öffentliche Teil von "fritz" seinem SSH-Schlüssel muss beim Benutzer "root" in der VM hinterlegt werden ⇒ Schlüsselpaar generieren
Dann ist das stoppen der VM viel einfacher.
Auch wenn das Verzeichnis /home/Minecraft/ in diesem Fall unter /home/ liegt, ist es kein Home-Verzeichnis.
Ich habe es nur als allgemeinen Ablageort für die Dateien bezüglich dieser VM gewählt:
> ls -lha /home/Minecraft/ drwxr-xr-x 3 root wheel 10B 13 Nov. 02:22 . drwxr-xr-x 31 root wheel 52B 13 Nov. 09:13 .. -rwxr-xr-x 1 root wheel 754B 13 Nov. 09:11 Minecraft_VM.sh drwxr-xr-x 2 root wheel 3B 13 Nov. 01:56 bin -rw-r--r-- 1 root wheel 32B 13 Nov. 00:59 device.map -rw-r--r-- 1 root wheel 100G 13 Nov. 09:50 linux.img -rwx------ 1 root wheel 787M 12 Nov. 23:10 ubuntu-20.04-legacy-server-amd64.iso > ls -lha /home/Minecraft/bin/ drwxr-xr-x 2 root wheel 3B 13 Nov. 01:56 . drwxr-xr-x 3 root wheel 10B 13 Nov. 02:22 .. -rwxr-xr-x 1 root wheel 88B 13 Nov. 01:58 mc.sh
- /home/Minecraft/Minecraft_VM.sh
#!/bin/bash VM_GAST="Minecraft" HDD="linux.img" CDROM="ubuntu-20.04-legacy-server-amd64.iso" CPU="2" RAM="16G" NETZWK="tap0" #==============================================================================# cd $(dirname ${0}) || exit 123 ps alxwww | fgrep -v grep | fgrep grub-bhyve | fgrep Minecraft && killall grub-bhyve sleep 0.5 ps alxwww | fgrep -v grep | fgrep grub-bhyve | fgrep Minecraft && killall grub-bhyve sleep 0.5 grub-bhyve -m device.map -r hd0,msdos1 -M ${RAM} ${VM_GAST} bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,${NETZWK} -s 3:0,virtio-blk,./${HDD} -l com1,stdio -c ${CPU} -m ${RAM} ${VM_GAST} bhyvectl --destroy --vm=${VM_GAST} ls -lha /dev/vmm/ #==============================================================================#
- /home/Minecraft/bin/mc.sh
#!/bin/bash screen -S Minecraft /home/Minecraft/Minecraft_VM.sh
> echo "fritz ALL=NOPASSWD:/home/Minecraft/bin/mc.sh" > /usr/local/etc/sudoers.d/minecraft
starten:
[fritz@server ~]$ sudo /home/Minecraft/bin/mc.sh
Kontrolle:
[fritz@server ~]$ sudo /home/Minecraft/bin/mc.sh
[fritz@server ~]$ ls -lha /dev/vmm/
total 2
dr-xr-xr-x 2 root wheel 512B 13 Nov. 09:22 .
dr-xr-xr-x 36 root wheel 512B 3 Nov. 11:01 ..
crw------- 1 root wheel 0x9b 13 Nov. 09:22 Minecraft
[root@server ~]# screen -ls
There are screens on:
3793.Minecraft (Detached)
1 Socket in /tmp/screens/S-root.
"fritz" verbindet sich über das Netzwerk mit der VM:
[fritz@server ~]$ ssh root@192.168.1.250
"root" öffnet den Screen, in dem die VM läuft (Konsolenzugang):
[root@server ~]# screen -x Minecraft
stoppen:
[fritz@server ~]$ ssh root@192.168.1.250 halt -p
Minecraft in der VM installieren
soweit ist jetzt alles vorbereitet, jetzt kann Minecraft installiert werden ⇒ So erstellen Sie einen Minecraft-Server unter Ubuntu 20.04
Den gewünschten Minecraft-Server kann man beispielsweise von hier (die neueste von spigot) oder hier (die stabilste von spigot) runterladen.
in der VM müssen folgende Kommandos ausgeführt werden:
root@minecraft:~# apt update root@minecraft:~# apt full-upgrade root@minecraft:~# apt install openjdk-11-jre-headless screen vim mc net-tools root@minecraft:~# mkdir Minecraft_Server root@minecraft:~# cd Minecraft_Server root@minecraft:~/Minecraft_Server# wget https://cdn.getbukkit.org/spigot/spigot-1.16.1.jar -O spigot-1.16.1.jar root@minecraft:~/Minecraft_Server# java -Xmx3G -Xms3G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -jar spigot-1.16.1.jar nogui root@minecraft:~/Minecraft_Server# echo "eula=true" >> eula.txt root@minecraft:~/Minecraft_Server# cp server.properties server.properties_original root@minecraft:~/Minecraft_Server# cat server.properties_original | sed "s/server-ip=.*/server-ip=$(hostname -i)/" > server.properties
Skripte zum starten des Minecraft-Servers
Das Ubuntu-Linux 20.04 wurde in der VM bei der Installation mit dem Hostnamen "minecraft", dem Benutzer "mc" und der IP "192.168.1.250" konfiguriert. Der Hostname und die IP wurden auch im DNS eingetragen.
Die VM sollte derart vorbereitet sein, dass "mc" sich passwortlos per ssh root@192.168.1.250 einloggen kann.
- dazu muss eine statische Netzwerkkonfiguration im VM-OS konfiguriert sein
- weiterhin muss der Benutzer "mc" einen SSH-Schlüssel besitzen
- und der öffentliche Teil von "mc" seinem SSH-Schlüssel muss beim Benutzer "root" in der VM hinterlegt werden ⇒ Schlüsselpaar generieren
Dann ist das stoppen der VM viel einfacher.
root@minecraft:~# ls -lh /root/ drwxr-xr-x 2 root root 4.0K Nov 13 13:33 bin drwx------ 7 root root 4.0K Nov 13 14:16 Minecraft_Server -rw-r--r-- 1 root root 0 Nov 13 11:13 systemctl
root@minecraft:~# ls -lh /root/bin/ -rwxr-xr-x 1 root root 620 Nov 13 13:33 mc.sh -rwxr-xr-x 1 root root 206 Nov 13 10:59 Start.sh
- /root/bin/mc.sh
#!/usr/bin/env bash # SERVER_JAR="spigot-1.16.1.jar" SPEICHER="3G" PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" echo java -Xmx3G -Xms3G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -jar spigot-1.16.1.jar nogui cd /root/Minecraft_Server/ && java -Xmx${SPEICHER} -Xms${SPEICHER} -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -jar ${SERVER_JAR} nogui #read PAUSE
- /root/bin/Start.sh
#!/usr/bin/env bash # PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" cd /root/Minecraft_Server/ || exit 123 screen -S Minecraft /root/bin/mc.sh
Start-Prozedur des Minecraft-Servers
einloggen in die VM:
[fritz@server ~]$ ssh root@192.168.1.250
Minecraft-Servers starten:
root@minecraft:~# /root/bin/Start.sh
aus dem Screen raus gehen:
[Strg]+[a],[d]
Kontrolle:
screen -ls
Stop-Prozedur des Minecraft-Servers
Entweder hat man die Konsole vom Start des Minecraft-Servers noch offen, dann kann man dort einfach "stop" eingeben.
… oder man muss sich wieder in die VM einloggen:
[fritz@server ~]$ ssh root@192.168.1.250
root@minecraft:~# screen -ls
There is a screen on:
1653.Minecraft (11/13/2020 01:33:14 PM) (Attached)
1 Socket in /run/screen/S-root.
root@minecraft:~# screen -x Minecraft
> stop
Port-Weiterleitung mit PF
NIC Passthrough - eine Netzwerkkarte alleine nur für die VM
> pciconf -v -l | fgrep -A1 -B3 network em1@pci0:0:31:6: class=0x020000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x0d4d subvendor=0x1849 subdevice=0x0d4d vendor = 'Intel Corporation' device = 'Ethernet Connection (11) I219-V' class = network subclass = ethernet
Ethernet Connection: em1@pci0:0:31:6 → 0/31/6
interaktiv:
> devctl set driver -f pci0:0:31:6 ppt
bootfest:
> echo 'pptdevs="0/31/6"' >> /boot/loader.conf > reboot
> pciconf -lv | fgrep -A1 -B3 network
ppt0@pci0:0:31:6: class=0x020000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x0d4d subvendor=0x1849 subdevice=0x0d4d
vendor = 'Intel Corporation'
device = 'Ethernet Connection (11) I219-V'
class = network
subclass = ethernet
… PCI passthrough requires direct memory allocation, hence the -S flags.
bhyve PCI pass-through to Linux guest
> grub-bhyve -m device.map -r hd0,msdos1 -S -M 4G Linux > bhyve -A -H -P -S -s 0:0,hostbridge -s 1:0,lpc -s 2:0,passthru,ppt0 -s 3:0,virtio-blk,./linux.img -l com1,stdio -c 1 -m 4G Linux > bhyvectl --destroy --vm=Linux > ls -lha /dev/vmm total 1 dr-xr-xr-x 2 root wheel 512B Mar 16 02:23 . dr-xr-xr-x 21 root wheel 512B Mar 16 03:12 .. crw------- 1 root wheel 0xae Mar 16 02:23 Linux
Wenn jetzt kein Ping durchgeht, dann hat man sicherlich vergessen, ein Eth-Kabel anzuschließen.
Test mit DVD-Image:
> bhyve -A -H -P -S -s 0:0,hostbridge -s 1:0,lpc -s 2:0,passthru,ppt0 -s 3:0,virtio-blk,./linux.img -s 4:0,ahci-hd,./dvd.img -l com1,stdio -c 1 -m 4G Linux
Wie kann man bhyve ein optisches, physisches Gerät (z.B.: /dev/cd0) übergeben? ⇒ https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=254813
GPU passthrough mit Bhyve
EuroBSDcon 2023
- GPU passthrough with bhyve - Corvin Köhne - EuroBSDcon 2023-09-16 ⇒
FreeBSD 14.0- GPU-passthrough wird genauso gemacht wie PCI-passthrough
Bhyve in FreeBSD 14.0 unterstützt AMD-Grafikkarten, Intel-Grafikkarten aber keine NVIDIA-Grafikkarten.
Für integrierten Intel-Grafikkarten muß Bhyve mit dem sysutils/edk2-Port ein Firmware-Update bekommen, dann funktioniert es. Bei NVIDIA-Grafikkarten funktioniert der Reset nicht, d.h. beim ersten Start funktioniert alles aber ein zweiter Start der VM funktioniert nicht, bis das Host-System rebootet wurde. Integrierte AMD-Grafikkarten funktionieren nicht.
Vorbereitungen in FreeBSD 14.0
Bhyve benötigt ein Firmware-Update aus dem Ports-Tree: sysutils/edk2
> cd /usr/ports/sysutils/edk2 > git remote -v
> kldload vmm > pciconf -l ... vgapci0@pci0:0:2:0: ... ... xhci0@pci0:0:20:0: ... ... > devctl detatch pci0:0:2:0 > devctl detatch pci0:0:20:0 > devctl set driver pci0:0:2:0 ppt > devctl set driver pci0:0:20:0 ppt > pciconf -l ... ppt0@pci0:0:2:0: ... ... ppt1@pci0:0:20:0: ... ...
AMD-GPU passthrough
Es funktionieren nur externe bzw. dedizierte Grafikkarten, interne AMD-Grafikkarten funktionieren nicht.
Call bhyve (es ist notwendig, von UEFI zu booten):
> bhyve -HPw -c 2 -m 4G -s 0,hostbridge -s 1,nvme,/root/linux.raw -s 2,passthru,0/2/0,rom=/root/vbios.rom -s 3,virtio-net,tap0 -s 31,lpc -l com1,stdio -l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd,fwcfg=qemu Linux
Intel-GPU passthrough
Interne Intel-Grafikkarten funktionieren, externe bzw. dedizierte Intel-Grafikkarten wurden noch nicht getestet.
Extract ROM (mit Linux):
> echo 1 > /sys/devices/pci0000:00/0000:00:02.0/rom > cat /sys/devices/pci0000:00/0000:00:02.0/rom > vbios.rom > echo 0 > /sys/devices/pci0000:00/0000:00:02.0/rom
Manchmal kann man das VBIOS nicht dumpen, dann muß man seinen Mainboard-Hersteller nach einem GOP fragen. Das VBIOS ist nicht wirklich zwingend nötig aber es ist sehr hilfreich!
Call bhyve (es ist notwendig, von UEFI zu booten):
> bhyve -AHPw -c 2 -m 4G -s 0,hostbridge -s 1,nvme,/root/linux.raw -s 2,passthru,0/2/0,rom=/root/vbios.rom -s 20,passthru,0/20/0 -s 3,virtio-net,tap0 -s 31,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 -l com1,stdio -l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd,fwcfg=qemu Linux
Hier wird die Option -A benötigt und man sollte darauf auchten, die Grafik über Slot "2" einzubinden und LPC muß über Slot "31" eingebunden werden!
NVIDIA-GPU passthrough
NVIDIA-Grafikkarten funktionieren nur beim ersten Mal, wenn man die VM restartet, dann funktioniert es nicht mehr. Erst nach einem Reboot des Host-Systems kann man die VM wieder starten.
EuroBSDcon 2022
- GPU passthrough with bhyve - Corvin Köhne - EuroBSDcon 2022 ⇒
FreeBSD 13.1
Nur Standard-PCI-AMD-Grafikkarten (auch Windows) und integrierte Intel-Grafik (nur Linux + FreeBSD) können genutzt werden, mit integrierter AMD-Grafik funktioniert es nicht! An der Unterstützung von NVIDIA-Grafikkarten wird gearbeitet, funktioniert aber noch nicht.
auf dem Host:
> pciconf -l ... vgapci0@pci0:0:2:0: ... ... xhci0@pci0:0:20:0: ... ... > kldload vmm > devctl detatch pci0:0:2:0 > devctl detatch pci0:0:20:0 > devctl set driver pci0:0:20:0 ppt > devctl set driver pci0:0:2:0 ppt > pciconf -l ... ppt1@pci0:0:2:0: ... ... ppt0@pci0:0:20:0: ... ... > bhyve -AHPSw -c cores=8 -m 8G -s 0,hostbridge -s 1,nvme,/root/linux.raw -s 2,passthru,0/2/0,rom=/root/gop.rom -s 20,passthru,0/20/0 -s 4,virtio-net,tap0 -s 31,lpc -l com1,stdio -l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd Linux
in der VM:
# dmidcode | grep -EA3 '^System Information'
System Information
Manufacturer: FreeBSD
Product Name: BHYVE
Version: 1.0
> lspci -v -s 0:2.0
00:02.0 VGA compatible controller: Intel Comporation HD Grafics 630 (rev 04)
Subsytem: Intel Comporation HD Grafics 630
...
Ca. 79% (Benchmark 182/231) der 2D-Grafikleistung und ca. 92% (Benchmark 1080/1178) der 3D-Grafikleistung des nativen Host-Systems kann in der VM genutzt werden.
Der GOP-Treiber (Graphics Output Protocol) für AMD- und NVIDIA-Grafikkarten ist im VBIOS enthalten und das VBIOS kann gedumpt werden.
Einzig verbliebene Schwierigkeit ist, wie bekommt man den GOP-Treiber für Intel-Grafik. Da gibt es noch keinen einheitlichen Weg für. Der in diesem Beispiel verwendete Treiber "gop.rom" stammt von dieser Webseite (Intel-ACRN): https://projectacrn.github.io/3.0/tutorials/gpu-passthru.html#steps
siehe https://youtu.be/vnicQZvW0vs?t=1254 für VBIOS für AMD-Grafikkarten und https://youtu.be/vnicQZvW0vs?t=1329 für integrierte Intel-Grafik.
Auf Windows kann man es mit GPU-Z dumpen.
Auf Linux kann das VBIOS wie folgt gedumpt werden:
> echo 1 > /sys/devices/pci0000:00/0000:00:02.0/rom > cat /sys/devices/pci0000:00/0000:00:02.0/rom > vbios.rom > echo 0 > /sys/devices/pci0000:00/0000:00:02.0/rom
Auf FreeBSD ???
Wenn man sich ein VBIOS aus dem Internet besorgt, dann muß man aufpassen, dass es von der gleichen Version ist, wie das im Host-System.
... -s 2,passthru,0/2/0,rom=/root/vbios.rom
