From c7ba149dbad3fb2de9b920b9c1933ea60760c8f8 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 11 Dec 2019 23:41:39 +0000 Subject: [PATCH] Emulate reads of the PCI command register for passthrough devices. VFs return zero for the memory enable bit even if it has been set by a prior write. After r348779 this caused the annoying behavior that a guest OS would unintentionally disable memory decoding on a future read-modify-write operation on the command register. Instead, return the shadow value of the command register for reads. This ensures that the guest will only toggle the state of the memory enable bit when it specifically intends to do so. MFC after: 2 weeks Sponsored by: Chelsio Communications --- usr.sbin/bhyve/pci_passthru.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c index 40bbc4c7827..b3d4faa3da0 100644 --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -803,6 +803,19 @@ passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, } #endif + /* + * Emulate the command register. If a single read reads both the + * command and status registers, read the status register from the + * device's config space. + */ + if (coff == PCIR_COMMAND) { + if (bytes <= 2) + return (-1); + *rv = pci_get_cfgdata16(pi, PCIR_COMMAND) << 16 | + read_config(&sc->psc_sel, PCIR_STATUS, 2); + return (0); + } + /* Everything else just read from the device's config space */ *rv = read_config(&sc->psc_sel, coff, bytes);