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 @@ -607,6 +607,7 @@ { int error; struct passthru_softc *sc; + uint16_t cmd; uint8_t intline, intpin; error = 1; @@ -618,16 +619,18 @@ 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(). + * Copy physical PCI header to virtual config space. COMMAND, + * INTLINE, and INTPIN shouldn't be aligned with their + * physical value and they are already set by pci_emul_init(). */ + cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); 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, pci_host_read_config(&sc->psc_sel, i, 4)); } + pci_set_cfgdata16(pi, PCIR_COMMAND, cmd); pci_set_cfgdata8(pi, PCIR_INTLINE, intline); pci_set_cfgdata8(pi, PCIR_INTPIN, intpin); @@ -643,13 +646,6 @@ goto done; } - pci_host_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 (pci_msix_table_bar(pi) >= 0) { error = init_msix_table(sc); if (error != 0) { @@ -919,7 +915,7 @@ passthru_cfgread_emulate, passthru_cfgwrite_emulate)) != 0) goto done; - /* Allow access to the physical command and status register. */ + /* Allow access to the physical status register. */ if ((error = set_pcir_handler(sc, PCIR_COMMAND, 0x04, NULL, NULL)) != 0) goto done; @@ -1073,28 +1069,26 @@ return (0); } -#ifdef LEGACY_SUPPORT /* - * If this device does not support MSI natively then we cannot let - * the guest disable legacy interrupts from the device. It is the - * legacy interrupt that is triggering the virtual MSI to the guest. + * The command register is emulated, but the status register + * is passed through. */ - if (sc->psc_msi.emulated && pci_msi_enabled(pi)) { - if (coff == PCIR_COMMAND && bytes == 2) - val &= ~PCIM_CMD_INTxDIS; - } -#endif - - pci_host_write_config(&sc->psc_sel, coff, bytes, val); if (coff == PCIR_COMMAND) { + if (bytes <= 2) + return (-1); + + /* Update the physical status register. */ + pci_host_write_config(&sc->psc_sel, PCIR_STATUS, val >> 16, 2); + + /* Update the virtual command register. */ cmd_old = pci_get_cfgdata16(pi, PCIR_COMMAND); - if (bytes == 1) - pci_set_cfgdata8(pi, PCIR_COMMAND, val); - else if (bytes == 2) - pci_set_cfgdata16(pi, PCIR_COMMAND, val); + pci_set_cfgdata16(pi, PCIR_COMMAND, val & 0xffff); pci_emul_cmd_changed(pi, cmd_old); + return (0); } + pci_host_write_config(&sc->psc_sel, coff, bytes, val); + return (0); }