diff --git a/usr.sbin/bhyve/amd64/pci_gvt-d.c b/usr.sbin/bhyve/amd64/pci_gvt-d.c --- a/usr.sbin/bhyve/amd64/pci_gvt-d.c +++ b/usr.sbin/bhyve/amd64/pci_gvt-d.c @@ -20,6 +20,7 @@ #include "amd64/e820.h" #include "pci_gvt-d-opregion.h" #include "pci_passthru.h" +#include "pciids_intel_gpus.h" #define KB (1024UL) #define MB (1024 * KB) @@ -41,6 +42,89 @@ #define GVT_D_MAP_OPREGION 1 #define GVT_D_MAP_VBT 2 +static int +set_bdsm_gen3(struct pci_devinst *const pi, vm_paddr_t bdsm_gpa) +{ + struct passthru_softc *sc = pi->pi_arg; + uint32_t bdsm; + int error; + + bdsm = pci_host_read_config(passthru_get_sel(sc), PCIR_BDSM, 4); + + /* Protect the BDSM register in PCI space. */ + pci_set_cfgdata32(pi, PCIR_BDSM, + bdsm_gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1))); + error = set_pcir_handler(sc, PCIR_BDSM, 4, passthru_cfgread_emulate, + passthru_cfgwrite_emulate); + if (error) { + warnx("%s: Failed to setup handler for BDSM register!", __func__); + return (error); + } + + return (0); +} + +struct igd_ops { + int (*set_bdsm)(struct pci_devinst *const pi, vm_paddr_t bdsm_gpa); +}; + +static const struct igd_ops igd_ops_gen3 = { .set_bdsm = set_bdsm_gen3 }; + +struct igd_device { + uint32_t device_id; + const struct igd_ops *ops; +}; + +#define IGD_DEVICE(_device_id, _ops) \ + { \ + .device_id = (_device_id), \ + .ops = (_ops), \ + } + +static const struct igd_device igd_devices[] = { + INTEL_I915G_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_I915GM_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_I945G_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_I945GM_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_VLV_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_PNV_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_I965GM_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_GM45_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_G45_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_ILK_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_SNB_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_IVB_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_HSW_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_BDW_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_CHV_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_SKL_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_BXT_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_KBL_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_CFL_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_WHL_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_CML_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_GLK_IDS(IGD_DEVICE, &igd_ops_gen3), + INTEL_CNL_IDS(IGD_DEVICE, &igd_ops_gen3), +}; + +static const struct igd_ops * +get_igd_ops(struct pci_devinst *const pi) +{ + struct passthru_softc *sc = pi->pi_arg; + uint16_t device_id; + + device_id = pci_host_read_config(passthru_get_sel(sc), PCIR_DEVICE, + 0x02); + for (size_t i = 0; i < nitems(igd_devices); i++) { + if (igd_devices[i].device_id != device_id) + continue; + + return (igd_devices[i].ops); + } + + return (NULL); +} + static int gvt_d_probe(struct pci_devinst *const pi) { @@ -108,8 +192,8 @@ { struct passthru_softc *sc; struct passthru_mmio_mapping *gsm; + const struct igd_ops *igd_ops; size_t sysctl_len; - uint32_t bdsm; int error; sc = pi->pi_arg; @@ -170,12 +254,14 @@ "Warning: Unable to reuse host address of Graphics Stolen Memory. GPU passthrough might not work properly."); } - bdsm = pci_host_read_config(passthru_get_sel(sc), PCIR_BDSM, 4); - pci_set_cfgdata32(pi, PCIR_BDSM, - gsm->gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1))); + igd_ops = get_igd_ops(pi); + if (igd_ops == NULL) { + warn("%s: Unknown IGD device. It's not supported yet!", + __func__); + return (-1); + } - return (set_pcir_handler(sc, PCIR_BDSM, 4, passthru_cfgread_emulate, - passthru_cfgwrite_emulate)); + return (igd_ops->set_bdsm(pi, gsm->gpa)); } static int