Index: usr.sbin/bhyve/pci_passthru.c =================================================================== --- usr.sbin/bhyve/pci_passthru.c +++ usr.sbin/bhyve/pci_passthru.c @@ -548,13 +548,6 @@ sc->psc_bar[i].lobits = lobits; pi->pi_bar[i].lobits = lobits; - /* The MSI-X table needs special handling */ - if (i == pci_msix_table_bar(pi)) { - error = init_msix_table(ctx, sc, base); - if (error) - return (-1); - } - /* * 64-bit BAR takes up two slots so skip the next one. */ @@ -567,6 +560,23 @@ return (0); } +static int +cfginitpcimsixtablebar(struct vmctx *ctx, struct passthru_softc *sc) +{ + int i, error; + + for (i = 0; i <= PCI_BARMAX; i++) { + /* The MSI-X table needs special handling */ + if (i == pci_msix_table_bar(sc->psc_pi)) { + error = init_msix_table(ctx, sc, sc->psc_bar[i].addr); + if (error) + return (-1); + } + } + + return (0); +} + static int cfginit(struct vmctx *ctx, struct pci_devinst *pi, int bus, int slot, int func) { @@ -596,6 +606,16 @@ write_config(&sc->psc_sel, PCIR_COMMAND, 2, pci_get_cfgdata16(pi, PCIR_COMMAND)); + /* + * We need to do this after PCIR_COMMAND got possibly updated, e.g., + * a BAR was enabled, as otherwise the PCIOCBARMMAP might fail on us. + */ + if (cfginitpcimsixtablebar(ctx, sc) != 0) { + warnx("failed to initialize MSI-X table for PCI %d/%d/%d", + bus, slot, func); + goto done; + } + error = 0; /* success */ done: return (error);