Hi All, I have this working for linux guests (Ubuntu) and a windows 10 guest without changing the kvm string in the file below:
/usr/src/freebsd/sys/amd64/vmm/x86.c:
This is what is in my file:
C:
static const char bhyve_id[12] = "KVMKVMKVM\0\0\0";
Hardware details:
Dell R720 Server With:
CPU 1 - Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
- Virtualization Tech (VT) capable=YES enabled=YES
CPU 2 - Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
- Virtualization Tech (VT) capable=YES enabled=YES
Memory = 96GB DDR-3 Dual Rank Multi-bit ECC
GPU - Tesla P4 (10DE,1BB3,10DE,11D8) S:00,B:02,D:00,F:00 (Upgraded to the latest firmware)
- This is a compute only GPU, there are no input and output devices
Comparing the code changes with github reveals the below changes by Corvin:
# freebsd/freebsd-src branch: main
# Beckhoff/freebsd-src branch: phab/corvink/15.0/nvidia-wip
# Files changed:
# usr.sbin/bhyve/amd64/Makefile.inc
# usr.sbin/bhyve/amd64/pci_gvt-d.c
# usr.sbin/bhyve/pci_emul.c
# usr.sbin/bhyve/pci_passthru.c
# usr.sbin/bhyve/pci_passthru.h
# usr.sbin/bhyve/pci_passthru_quirks.c
# freebsd/freebsd-src branch: releng/14.2
# Beckhoff/freebsd-src branch: phab/corvink/14.2/nvidia-wip
# Files Changed:
# sys/dev/pci/pcireg.h
# usr.sbin/bhyve/pci_passthru.c
# freebsd/freebsd-src branch: releng/14.0
# Beckhoff/freebsd-src branch: phab/corvink/14.0/nvidia-wip
# Files Changed:
# sys/amd64/vmm/x86.c
# sys/dev/pci/pcireg.h
# usr.sbin/bhyve/pci_passthru.c
# usr.sbin/bhyve/usb_mouse.c
Below are the steps I followed for testing this:
# install git
pkg update
pkg install git
#### Create a diff / patch file for FreeBSD 14.2 release for passing nvidia GPU to linux guests
# 1. Clone the two repos
cd /usr/src
git clone https://github.com/Beckhoff/freebsd-src.git beckhoff
# 2. Checkout the correct branch
cd ../beckhoff
git checkout phab/corvink/14.2/nvidia-wip
# 3. change the bhyve_id string to work with linux guests
# -static const char bhyve_id[12] = "bhyve bhyve "; # windows
# +static const char bhyve_id[12] = "KVMKVMKVM\0\0\0"; # linux
ee sys/amd64/vmm/x86.c
# change:
# static const char bhyve_id[12] = "KVMKVMKVM\0\0\0";
git add -u
git commit -m "Apply local patch to string in bhyve_id for Linux guests"
# 4. Add the FreeBSD source as remote repo
git remote add freebsd https://github.com/freebsd/freebsd-src.git
git fetch freebsd releng/14.2
# 5. Generate the diff for three affected files (Linux guests)
git diff --src-prefix=a/ --dst-prefix=b/ \
freebsd/releng/14.2..HEAD \
-- sys/amd64/vmm/x86.c \
sys/dev/pci/pcireg.h \
usr.sbin/bhyve/pci_passthru.c \
> ../freebsd-14.2-beckhoff-linux.patch
# 6. Generate the diff for two affected files (Windows guests)
git diff --src-prefix=a/ --dst-prefix=b/ \
freebsd/releng/14.2..HEAD \
-- sys/dev/pci/pcireg.h \
usr.sbin/bhyve/pci_passthru.c \
> ../freebsd-14.2-beckhoff-windows.patch
# 7. Inspect the patches
less ../freebsd-14.2-beckhoff-linux.patch
less ../freebsd-14.2-beckhoff-windows.patch
# 8. Apply the patches to a clean FreeBSD 14.2 source
cd ../freebsd
git apply ../freebsd-14.2-beckhoff-linux.patch
git commit -am "Apply patch for passthrough of Nvidia GPU to linux guest in bhyve"
# 9. Backup the original executables before building new ones
mkdir -p ~/bhyve
cp /usr/sbin/bhyve ~/bhyve/
cp /boot/modules/vmm.ko ~/bhyve/
# 10. Get the script for building and upgrading the software and kernel and execute it
fetch https://forums.freebsd.org/attachments/build-txt.21848/ -o ./build.sh
chmod 700 ./build.sh
./build.sh --without-bhf --verbose --src-dir=/usr/src/freebsd/
# Determine your PCI bus, slot and function
dmesg | grep -B4 vga
# 11. Add the below tunables to /boot/loader.conf to load on system boot
sysrc -f /boot/loader.conf vmm_load="YES"
sysrc -f /boot/loader.conf pptdevs="66/0/0"
# 12. reboot the system
shutdown -r now
#### Start Bhyve work
# 1. Create a tap interface for the network device in the VM to attach to.
ifconfig tap0 create
sysctl net.link.tap.up_on_open=1
# 2. create a bridge
ifconfig bridge2 create
ifconfig bridge2 addm em0 addm tap0
ifconfig bridge2 up
# 3. to use UEFI install the pkg bhyve-firmware
pkg install bhyve-firmware
# 4. Create a new zfs dataset to use for vm's:
zfs create zroot/vm
zfs create zroot/vm/ubuntu
# 5. create a zvolume
zfs create -V 30G zroot/vm/ubuntu/disk0
# 6. copy the file BHYVE_UEFI.fd to your working folder
cp /usr/local/share/uefi-firmware/BHYVE_UEFI.fd /zroot/vm/ubuntu/linuxguest_VARS.fd
# 7. download Ubuntu
fetch -o /zroot/vm/ubuntu/ubuntu-24.04.2-live-server-amd64.iso https://releases.ubuntu.com/24.04.2/ubuntu-24.04.2-live-server-amd64.iso?_gl=1*qc99qr*_gcl_au*NTczODEwNTIuMTc1MTc0NDc2Ny4xNTAzMzM2MDYzLjE3NTE3NDUwNDQuMTc1MTc0NTA0NA..
# 8. change to the directory
cd /zroot/vm/ubuntu
# 9. execute the bhyve command
bhyve -c 4 -m 8192M -H -A -P -S -W -w \
-s 0,hostbridge \
-s 3,ahci-cd,./ubuntu-24.04.2-live-server-amd64.iso \
-s 4,ahci-hd,/dev/zvol/zroot/vm/ubuntu/disk0 \
-s 5,virtio-net,tap0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
ubuntu-24-04-2
# 10. Follow the steps to install ubuntu and power off the system or reboot once it prompts
# 11. recreate the bhyve session this time passing the GPU and removing the CD device
bhyve -c 4 -m 8192M -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/ubuntu/disk0 \
-s 5,virtio-net,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
ubuntu-24-04-2
# I searched using nvidia website to determine which driver to install
# turns out with ubuntu 24.04.2 the 570 series driver is recommended
# 12. Install the driver:
sudo apt install nvidia-driver-570
# 13. blacklist nouveau
sudo nano /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
sudo update-initramfs -u
# 14. Update grub for nomodeset since this is a Tesla P4
sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="nomodeset"
sudo update-grub
# 15. now powerdown and restart the vm
sudo poweroff
# 16. Enter bhyve again
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/ubuntu/disk0 \
-s 5,virtio-net,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
ubuntu-24-04-2
# 17. Test nvidia-smi
nvidia-smi
# Success
# 18. Get and install plex
cd ~/
wget https://downloads.plex.tv/plex-media-server-new/1.42.1.10060-4e8b05daf/debian/plexmediaserver_1.42.1.10060-4e8b05daf_amd64.deb?_gl=1*b0riic*_gcl_au*NjQ0NjMzMTUuMTc1NTI4NDYyOQ..*_ga*MTU0MDY3MjIzNC4xNzM5NTAxNDQ1*_ga_G6FQWNSENB*czE3NTUyODQ2MjgkbzE4JGcxJHQxNzU1Mjg0NjY0JGoyNCRsMCRoMA.. -O plexmediaserver_1.42.1.deb
sudo dpkg -i plexmediaserver_1.42.1.deb
# 19. Grab some media from my share
sudo apt update
sudo apt install smbclient
sudo smbclient //192.168.3.102/data -U "AD\Clint"
timeout 300
get file.mkv
# Setup plex and verify the graphics card is available for use.
# tested selecting graphics card and transcoding everything seems to work perfect.
# manually selecting the quality causes issues. Seems like a plex issue. Automatically selecting quality works perfectly.
#### Test building FreeBSD for windows to verify
ZioMario suggestion that this is required.
# 1. backup files /boot/modules/vmm.ko and /usr/sbin/bhyve
mv /boot/modules/vmm.ko ~/bhyve/vmm_lin.ko
mv /usr/sbin/bhyve ~/bhyve/byhve_lin
# 2. change the bhyve_id string for windows systems
ee /usr/src/freebsd/sys/amd64/vmm/x86.c
static const char bhyve_id[12] = "bhyve bhyve ";
git add -u
git commit -m "Apply local patch to string in bhyve_id for Windows guests"
# 3. Rebuild for windows
./build.sh --without-bhf --verbose --src-dir=/usr/src/freebsd/
# 4. reboot after building is complete
shutdown -r now
# 5. Enter ubuntu bhyve again
cd /zroot/vm/ubuntu
bhyve -c 4 -m 8192M -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/ubuntu/disk0 \
-s 5,virtio-net,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
ubuntu-24-04-2
# 6. Test nvidia-smi
nvidia-smi
# This time it fails.
# 7. Save the bhyve executable as the windows Version
cp /boot/modules/vmm.ko ~/bhyve/vmm_win.ko
cp /usr/sbin/bhyve ~/bhyve/byhve_win
# 8. Create a new zfs dataset for my windows vm:
zfs create zroot/vm/win10
# 9. create a zvolume
zfs create -V 60G -b 32K zroot/vm/win10/disk0
# 10. copy the file BHYVE_UEFI.fd to your working folder
cp /usr/local/share/uefi-firmware/BHYVE_UEFI.fd /zroot/vm/win10/linuxguest_VARS.fd
# 11. Download the media creation tool from windows and create a bootable iso.
# I drop the bootable iso on my samba share
# 12. get the windows iso using samba client may require to install smbclient
smbclient //192.168.3.102/share -U AD\\Clint
timeout 300
get Windows.iso /zroot/vm/win10/
# 13. change to the directory
cd /zroot/vm/win10
# 14. execute the bhyve command, the virtio-net doesn't work, but this is desirable as I don't want to sign in with a M$ account.
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 3,ahci-cd,./Windows.iso \
-s 4,ahci-hd,/dev/zvol/zroot/vm/win10/disk0 \
-s 5,virtio-net,tap0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
win10
# 15. Install windows, after installation remove the cd drive and reboot with no internet
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/win10/disk0 \
-s 5,virtio-net,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
win10
# 16. Restart the vm with internet now using e1000 device attached to the tap0
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/win10/disk0 \
-s 5,e1000,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
win10
# 17. Download and install nvidia drivers and plex media server
# Once complete add some media from my samba share by copying a video file for testing transcoding
# map a drive with AD\Clint as the user and enter my password and check the check box to remember the login details.
# The nvidia driver recommended by nvidia website 580.88 doesn't work.
# I used the nvidia driver 538.78 and it seems to work.
# 18. Restart the vm
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/win10/disk0 \
-s 5,e1000,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
win10
# 19. Open an elevated command prompt
nvidia-smi
# success.
# 20. Setup plex and verify the graphics card is available for use.
# tested selecting graphics card and transcoding, everything seems to work perfect.
# manually selecting the quality causes issues. Seems like a plex issue. Automatically selecting quality works perfectly. Shutdown the vm.
# 21. replace bhyve and vmm.ko with the linux version and reboot
cp -i ~/bhyve/bhyve_lin /usr/sbin/bhyve
cp -i ~/bhyve/vmm_lin.ko /boot/modules/vmm.ko
cp -i ~/bhyve/vmm_lin.ko /boot/kernel/vmm.ko
# 22. Restart the VM to test with the linux built vmm.ko and bhyve.
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/win10/disk0 \
-s 5,e1000,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
win10
# 23. Setup plex and verify the graphics card is available for use.
# tested selecting graphics card and transcoding, everything seems to work perfect.
# manually selecting the quality causes issues. Seems like a plex issue. Automatically selecting quality works perfectly. Shutdown the vm.
# Just to be sure, I apply the patch again:
ee /usr/src/freebsd/sys/amd64/vmm/x86.c
static const char bhyve_id[12] = "KVMKVMKVM\0\0\0";
cd /usr/src/freebsd/
git add -u
git commit -am "Apply patch for passthrough of Nvidia GPU to linux guest in bhyve"
./build.sh --without-bhf --verbose --src-dir=/usr/src/freebsd/
shutdown -r now
# enter windows bhyve again to see if it is working.
cd /zroot/vm/win10
bhyve -c 16 -m 32G -H -A -P -S \
-s 0,hostbridge \
-s 4,ahci-hd,/dev/zvol/zroot/vm/win10/disk0 \
-s 5,e1000,tap0 \
-s 6,passthru,66/0/0 \
-s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l bootrom,./linuxguest_VARS.fd \
win10
# test plex again and nvidia-smi
# works as expected.
ZioMario, I can confirm there is no need to create a different vmm.ko and bhyve executables for Nvidia GPU passthrough in both Windows and Linux VM's at least on my hardware. In the file /usr/src/freebsd/sys/amd64/vmm/x86.c Windows seems to work fine with either of the strings below:
C:
static const char bhyve_id[12] = "bhyve bhyve ";
static const char bhyve_id[12] = "KVMKVMKVM\0\0\0";
However, Linux only works only with the string:
C:
static const char bhyve_id[12] = "KVMKVMKVM\0\0\0";
I have attached the patch file that works for both Linux and Windows guests. This patch should be applied to a fresh FreeBSD 14.2 source.
cd /usr/src/
git clone https://github.com/freebsd/freebsd-src.git
git fetch freebsd releng/14.2
cd freebsd
git apply freebsd-14.2-beckhoff-linux.patch.txt
grab the build.sh script and build everything like I did in the previous steps.