diff --git a/usr.sbin/bhyve/pci_passthru.h b/usr.sbin/bhyve/pci_passthru.h --- a/usr.sbin/bhyve/pci_passthru.h +++ b/usr.sbin/bhyve/pci_passthru.h @@ -20,5 +20,9 @@ uint32_t read_config(const struct pcisel *sel, long reg, int width); void write_config(const struct pcisel *sel, long reg, int width, uint32_t data); +int passthru_cfgread_emulate(struct passthru_softc *sc, struct pci_devinst *pi, + int coff, int bytes, uint32_t *rv); +int passthru_cfgwrite_emulate(struct passthru_softc *sc, struct pci_devinst *pi, + int coff, int bytes, uint32_t val); int set_pcir_handler(struct passthru_softc *sc, int reg, int len, cfgread_handler rhandler, cfgwrite_handler whandler); diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -603,6 +603,7 @@ { int error; struct passthru_softc *sc; + uint8_t intline, intpin; error = 1; sc = pi->pi_arg; @@ -612,6 +613,19 @@ sc->psc_sel.pc_dev = slot; sc->psc_sel.pc_func = func; + /* + * Copy physical PCI header to virtual config space. INTLINE and INTPIN + * shouldn't be aligned with their physical value and they are already set by + * pci_emul_init(). + */ + intline = pci_get_cfgdata8(pi, PCIR_INTLINE); + intpin = pci_get_cfgdata8(pi, PCIR_INTPIN); + for (int i = 0; i <= PCIR_MAXLAT; i += 4) { + pci_set_cfgdata32(pi, i, read_config(&sc->psc_sel, i, 4)); + } + pci_set_cfgdata8(pi, PCIR_INTLINE, intline); + pci_set_cfgdata8(pi, PCIR_INTPIN, intpin); + if (cfginitmsi(sc) != 0) { warnx("failed to initialize MSI for PCI %d/%d/%d", bus, slot, func); @@ -876,6 +890,15 @@ get_config_value_node(nvl, "rom"))) != 0) goto done; + /* Emulate most PCI header register. */ + if ((error = set_pcir_handler(sc, 0, PCIR_MAXLAT + 1, + passthru_cfgread_emulate, passthru_cfgwrite_emulate)) != 0) + goto done; + + /* Allow access to the physical command and status register. */ + if ((error = set_pcir_handler(sc, PCIR_COMMAND, 0x04, NULL, NULL)) != 0) + goto done; + error = 0; /* success */ done: if (error) { @@ -885,16 +908,6 @@ return (error); } -static int -bar_access(int coff) -{ - if ((coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) || - coff == PCIR_BIOS) - return (1); - else - return (0); -} - static int msicap_access(struct passthru_softc *sc, int coff) { @@ -926,23 +939,11 @@ struct pci_devinst *pi __unused, int coff, int bytes, uint32_t *rv) { /* - * PCI BARs and MSI capability is emulated. + * MSI capability is emulated. */ - if (bar_access(coff) || msicap_access(sc, coff) || - msixcap_access(sc, coff)) + if (msicap_access(sc, coff) || msixcap_access(sc, coff)) return (-1); -#ifdef LEGACY_SUPPORT - /* - * Emulate PCIR_CAP_PTR if this device does not support MSI capability - * natively. - */ - if (sc->psc_msi.emulated) { - if (coff >= PCIR_CAP_PTR && coff < PCIR_CAP_PTR + 4) - return (-1); - } -#endif - /* * Emulate the command register. If a single read reads both the * command and status registers, read the status register from the @@ -962,6 +963,14 @@ return (0); } +int +passthru_cfgread_emulate(struct passthru_softc *sc __unused, + struct pci_devinst *pi __unused, int coff __unused, int bytes __unused, + uint32_t *rv __unused) +{ + return (-1); +} + static int passthru_cfgread(struct pci_devinst *pi, int coff, int bytes, uint32_t *rv) { @@ -982,12 +991,6 @@ int error, msix_table_entries, i; uint16_t cmd_old; - /* - * PCI BARs are emulated - */ - if (bar_access(coff)) - return (-1); - /* * MSI capability is emulated */ @@ -1054,6 +1057,14 @@ return (0); } +int +passthru_cfgwrite_emulate(struct passthru_softc *sc __unused, + struct pci_devinst *pi __unused, int coff __unused, int bytes __unused, + uint32_t val __unused) +{ + return (-1); +} + static int passthru_cfgwrite(struct pci_devinst *pi, int coff, int bytes, uint32_t val) {