---> NVIDIA GPU passthrough should work with stock 15.0, no patches
required.
Hello my friend. Unfortunately it does not. Not even with 15.0-p9. With my
system it didn't work. If you go on the FreeBSD forums you see people
saying that they are still using the passthru on FreeBSD 14. One user
offered a patch that I have applied,but it didn't work. So I worked with
Claude to fix the bug and after some days of work,we developed the correct
patches. Now it is working fine. I attach them here,if you want to give a
look.
On Fri, Jun 5, 2026 at 8:34 AM Corvin Köhne <[email protected]> wrote:
> On Thu, 2026-06-04 at 13:23 +0200, Mario Marietto wrote:
> > Hi everyone,
> > I'm trying to get NVIDIA GPU passthrough working with bhyve on FreeBSD
> 15.0-
> > RELEASE-p5, using Corvin Köhne's nvidia-wip branch:
> >
> https://github.com/Beckhoff/freebsd-src/tree/phab/corvink/15.0/nvidia-wip
> > The VM fails to start with the following error before the guest even
> boots:
> > bhyve: bootrom_alloc: vm_mmap_mapseg: Invalid argument
>
> NVIDIA GPU passthrough should work with stock 15.0, no patches required.
>
>
> --
> Best regards,
> Corvin
>
--
Mario.
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -755,10 +755,10 @@
sx_assert(&vm->mem.mem_segs_lock, SX_LOCKED);
for (i = 0; i < VM_MAX_MEMMAPS; i++) {
- if (!vm_memseg_sysmem(vm, i))
+ mm = &vm->mem.mem_maps[i];
+ if (!vm_memseg_sysmem(vm, mm->segid))
continue;
- mm = &vm->mem.mem_maps[i];
KASSERT((mm->flags & VM_MEMMAP_F_IOMMU) == 0,
("iommu map found invalid memmap %#lx/%#lx/%#x",
mm->gpa, mm->len, mm->flags));
@@ -803,10 +803,10 @@
sx_assert(&vm->mem.mem_segs_lock, SX_LOCKED);
for (i = 0; i < VM_MAX_MEMMAPS; i++) {
- if (!vm_memseg_sysmem(vm, i))
+ mm = &vm->mem.mem_maps[i];
+ if (!vm_memseg_sysmem(vm, mm->segid))
continue;
- mm = &vm->mem.mem_maps[i];
if ((mm->flags & VM_MEMMAP_F_IOMMU) == 0)
continue;
mm->flags &= ~VM_MEMMAP_F_IOMMU;
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -14,6 +14,7 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mman.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/sx.h>
@@ -74,14 +75,11 @@
static void devmem_destroy(void *arg);
static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem);
+/* VMM_PRIV_CHECK_FIX_APPLIED */
static int
-vmm_priv_check(struct ucred *ucred)
+vmm_priv_check(struct thread *td)
{
- if (jailed(ucred) &&
- !(ucred->cr_prison->pr_allow & pr_allow_flag))
- return (EPERM);
-
- return (0);
+ return (priv_check(td, PRIV_DRIVER));
}
static int
@@ -334,7 +332,7 @@
* A jail without vmm access shouldn't be able to access vmm device
* files at all, but check here just to be thorough.
*/
- error = vmm_priv_check(td->td_ucred);
+ error = vmm_priv_check(td);
if (error != 0)
return (error);
@@ -813,7 +811,7 @@
char *buf;
int error, buflen;
- error = vmm_priv_check(req->td->td_ucred);
+ error = vmm_priv_check(req->td);
if (error)
return (error);
@@ -902,7 +900,7 @@
char *buf;
int error, buflen;
- error = vmm_priv_check(req->td->td_ucred);
+ error = vmm_priv_check(req->td);
if (error != 0)
return (error);
@@ -925,7 +923,7 @@
{
int error;
- error = vmm_priv_check(td->td_ucred);
+ error = vmm_priv_check(td);
if (error != 0)
return (error);
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -390,6 +390,8 @@
* This is the usual case for the SYSMEM segment created by userspace
* loaders like bhyveload(8).
*/
+ if (segid != VM_SYSMEM) /* VM_ALLOC_MEMSEG_FIX_APPLIED */
+ goto alloc_devmem;
error = vm_get_memseg(ctx, segid, &memseg.len, memseg.name,
sizeof(memseg.name));
if (error)
@@ -404,6 +406,7 @@
}
}
+alloc_devmem:
bzero(&memseg, sizeof(struct vm_memseg));
memseg.segid = segid;
memseg.len = len;