bhyve: assign a valid INTPIN to NVIDIA GPUs

When passing an NVIDIA GPU to a Linux VM, the GPU driver refuses to work and
complains about a missing IRQ:

[ 77.208984] NVRM: Can't find an IRQ for your NVIDIA card!
[ 77.212697] NVRM: Please check your BIOS settings.
[ 77.212699] NVRM: [Plug & Play OS] should be set to NO
[ 77.212700] NVRM: [Assign IRQ to VGA] should be set to YES
[ 77.212702] nvidia: probe of 0000:00:07.0 failed with error -1

By setting a valid INTPIN in the PCI config space those error messages
disappear. Additionally, tools like nvidia-smi are able to detect the GPU and
the GPU driver seems to work properly.

Note that bhyve still doesn't support legacy interrupts. So, the guest
shouldn't try to use it even though we're assigning an INTPIN.

Reviewed by:		jhb
Tested by:		chuck
MFC after:		1 week
Sponsored by:		Beckhoff Automation GmbH & Co. KG
Differential Revision:	https://reviews.freebsd.org/D51892
This commit is contained in:
Corvin Köhne
2022-03-17 13:11:14 +01:00
parent 8c9a919aba
commit effcd0ded0
2 changed files with 49 additions and 0 deletions
+1
View File
@@ -13,6 +13,7 @@ SRCS+= \
pci_gvt-d.c \
pci_lpc.c \
pci_passthru.c \
pci_passthru_quirks.c \
pctestdev.c \
pm.c \
post.c \
+48
View File
@@ -0,0 +1,48 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Beckhoff Automation GmbH & Co. KG
* Author: Corvin Köhne <c.koehne@beckhoff.com>
*/
#include <dev/pci/pcireg.h>
#include <errno.h>
#include "pci_passthru.h"
#define PCI_VENDOR_NVIDIA 0x10DE
static int
nvidia_gpu_probe(struct pci_devinst *const pi)
{
struct passthru_softc *sc;
uint16_t vendor;
uint8_t class;
sc = pi->pi_arg;
vendor = pci_host_read_config(passthru_get_sel(sc), PCIR_VENDOR, 0x02);
if (vendor != PCI_VENDOR_NVIDIA)
return (ENXIO);
class = pci_host_read_config(passthru_get_sel(sc), PCIR_CLASS, 0x01);
if (class != PCIC_DISPLAY)
return (ENXIO);
return (0);
}
static int
nvidia_gpu_init(struct pci_devinst *const pi, nvlist_t *const nvl __unused)
{
pci_set_cfgdata8(pi, PCIR_INTPIN, 1);
return (0);
}
static struct passthru_dev nvidia_gpu = {
.probe = nvidia_gpu_probe,
.init = nvidia_gpu_init,
};
PASSTHRU_DEV_SET(nvidia_gpu);