Bhyve ist ein Hypervisor, auf dem Gastbetriebssysteme in einer virtuellen Maschine ausgeführt werden.
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" ...
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
VM-Start (virtio-9p):
# bhyve -AHP -s 0:0,hostbridge -s 3:0,ahci-cd,./debian-12.4.0-amd64-netinst.iso -s 4:0,virtio-blk,./linux.img -s 5,virtio-9p,sharename=/daten/mm -s 6:0,virtio-net,tap0 -s 31:0,lpc -l com1,stdio -c 4 -m 4G linuxguest
Mount mit Linux/FreeBSD
# mount -t 9p -o trans=virtio sharename /mm
Eintrag in der FsTab:
# vim /etc/fstab sharename /mm 9p trans=virtio,rw 0 0
VM-Start (virtio-9p):
# bhyve -AHP -s 0:0,hostbridge -s 3:0,ahci-cd,./debian-12.4.0-amd64-netinst.iso -s 4:0,virtio-blk,./linux.img -s 5,virtio-9p,mmaudio=/daten/mm/Audio -s 6,virtio-9p,mmvideo=/daten/mm/Video -s 7:0,virtio-net,tap0 -s 31:0,lpc -l com1,stdio -c 4 -m 4G linuxguest
Mount mit Linux/FreeBSD
# mount -t 9p -o trans=virtio mmaudio /mm/Audio # mount -t 9p -o trans=virtio mmvideo /mm/Video
Eintrag in der FsTab:
# vim /etc/fstab mmaudio /mm/Audio 9p trans=virtio,rw 0 0 mmvideo /mm/Video 9p trans=virtio,rw 0 0
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 vm0bhyve -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> pkg install sysutils/grub2-bhyve sysutils/bhyve-firmware
eine virtuelle Festplatte erstellen:
> truncate -s 20G linux.img
Map-Datei für den Grub anlegen:
> vi device.map (hd0) ./linux.img (cd0) ./debian-12.4.0-amd64-netinst.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,./debian-12.4.0-amd64-netinst.iso -l com1,stdio -c 4 -m 4G linuxguest > bhyvectl --destroy --vm=linuxguest
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
> 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:
> 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
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.
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
#!/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/ #==============================================================================#
#!/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
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
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.
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
#!/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
#!/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
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
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
> 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
FreeBSD 14.0Bhyve 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.
Extract ROM (mit Linux):
> lspci -v | grep -Fi vga 00:02.0 VGA compatible controller: ... > 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
FreeBSD-Host-System
> kldload vmm > pciconf -l | grep -Ei 'vga|xhci' vgapci0@pci0:0:2:0: ... xhci0@pci0:0:20:0: ... > devctl detach pci0:0:2:0 > devctl detach pci0:0:20:0 > devctl set driver pci0:0:2:0 ppt > devctl set driver pci0:0:20:0 ppt > pciconf -l | grep -Fi ppt ppt0@pci0:0:2:0: ... ppt1@pci0:0:20:0: ...
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
Interne Intel-Grafikkarten funktionieren, externe bzw. dedizierte Intel-Grafikkarten wurden noch nicht getestet.
Bhyve benötigt ein Firmware-Update aus dem Ports-Tree: sysutils/edk2
FreeBSD-Host-System
> cd /usr/ports/sysutils/edk2 > git remote -v ...
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-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.
FreeBSD 13.1Nur 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