git: e87a6f3ef284 - main - bhyve: use physical lobits for BARs of passthru devices

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Thu, 18 Nov 2021 15:28:03 UTC
The branch main has been updated by manu:

URL: https://cgit.FreeBSD.org/src/commit/?id=e87a6f3ef284593c01e0fd3f8b5bfc1f645e5b18

commit e87a6f3ef284593c01e0fd3f8b5bfc1f645e5b18
Author:     Corvin Köhne <CorvinK@beckhoff.com>
AuthorDate: 2021-11-18 15:25:09 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2021-11-18 15:25:09 +0000

    bhyve: use physical lobits for BARs of passthru devices
    
    Tell the guest whether a BAR uses prefetched memory or not for
    passthru devices by using the same lobits as the physical device.
    
    Reviewed by:     grehan
    Sponsored by:    Beckhoff Autmation GmbH & Co. KG
    Differential Revision:    https://reviews.freebsd.org/D32685
---
 usr.sbin/bhyve/pci_emul.c     | 16 ++++++++++++----
 usr.sbin/bhyve/pci_emul.h     |  1 +
 usr.sbin/bhyve/pci_passthru.c | 11 +++++++++++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index 86a2f995126e..bd94859c4ea1 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -707,6 +707,15 @@ pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type,
 	pdi->pi_bar[idx].type = type;
 	pdi->pi_bar[idx].addr = addr;
 	pdi->pi_bar[idx].size = size;
+	/*
+	 * passthru devices are using same lobits as physical device they set
+	 * this property
+	 */
+	if (pdi->pi_bar[idx].lobits != 0) {
+		lobits = pdi->pi_bar[idx].lobits;
+	} else {
+		pdi->pi_bar[idx].lobits = lobits;
+	}
 
 	/* Initialize the BAR register in config space */
 	bar = (addr & mask) | lobits;
@@ -1946,7 +1955,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
 			case PCIBAR_IO:
 				addr = *eax & mask;
 				addr &= 0xffff;
-				bar = addr | PCIM_BAR_IO_SPACE;
+				bar = addr | pi->pi_bar[idx].lobits;
 				/*
 				 * Register the new BAR value for interception
 				 */
@@ -1957,7 +1966,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
 				break;
 			case PCIBAR_MEM32:
 				addr = bar = *eax & mask;
-				bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
+				bar |= pi->pi_bar[idx].lobits;
 				if (addr != pi->pi_bar[idx].addr) {
 					update_bar_address(pi, addr, idx,
 							   PCIBAR_MEM32);
@@ -1965,8 +1974,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
 				break;
 			case PCIBAR_MEM64:
 				addr = bar = *eax & mask;
-				bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
-				       PCIM_BAR_MEM_PREFETCH;
+				bar |= pi->pi_bar[idx].lobits;
 				if (addr != (uint32_t)pi->pi_bar[idx].addr) {
 					update_bar_address(pi, addr, idx,
 							   PCIBAR_MEM64);
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
index 5b6a17119960..6eac0720f09f 100644
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -99,6 +99,7 @@ struct pcibar {
 	enum pcibar_type	type;		/* io or memory */
 	uint64_t		size;
 	uint64_t		addr;
+	uint8_t			lobits;
 };
 
 #define PI_NAMESZ	40
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index bf99c646c480..29142749abb4 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -531,12 +531,23 @@ cfginitbar(struct vmctx *ctx, struct passthru_softc *sc)
 		sc->psc_bar[i].type = bartype;
 		sc->psc_bar[i].size = size;
 		sc->psc_bar[i].addr = base;
+		sc->psc_bar[i].lobits = 0;
 
 		/* Allocate the BAR in the guest I/O or MMIO space */
 		error = pci_emul_alloc_bar(pi, i, bartype, size);
 		if (error)
 			return (-1);
 
+		/* Use same lobits as physical bar */
+		uint8_t lobits = read_config(&sc->psc_sel, PCIR_BAR(i), 0x01);
+		if (bartype == PCIBAR_MEM32 || bartype == PCIBAR_MEM64) {
+			lobits &= ~PCIM_BAR_MEM_BASE;
+		} else {
+			lobits &= ~PCIM_BAR_IO_BASE;
+		}
+		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);