summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/pci_passthru.c
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-02-01 03:49:09 +0000
committerneel <neel@FreeBSD.org>2013-02-01 03:49:09 +0000
commit81de6f5cc49043ac5e2135ad996dfb05f2bd2a32 (patch)
tree98f2e96d433580504233a3c13ced43451e5611ed /usr.sbin/bhyve/pci_passthru.c
parent803db8c37c2516174b23103ab861a500599042dc (diff)
downloadFreeBSD-src-81de6f5cc49043ac5e2135ad996dfb05f2bd2a32.zip
FreeBSD-src-81de6f5cc49043ac5e2135ad996dfb05f2bd2a32.tar.gz
Fix a broken assumption in the passthru implementation that the MSI-X table
can only be located at the beginning or the end of the BAR. If the MSI-table is located in the middle of a BAR then we will split the BAR into two and create two mappings - one before the table and one after the table - leaving a hole in place of the table so accesses to it can be trapped and emulated. Obtained from: NetApp
Diffstat (limited to 'usr.sbin/bhyve/pci_passthru.c')
-rw-r--r--usr.sbin/bhyve/pci_passthru.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index 131f08a..08a9a58 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -355,14 +355,18 @@ msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc,
static int
init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
{
- int idx;
- size_t table_size;
+ int b, s, f;
+ int error, idx;
+ size_t len, remaining, table_size;
vm_paddr_t start;
- size_t len;
struct pci_devinst *pi = sc->psc_pi;
assert(pci_msix_table_bar(pi) >= 0 && pci_msix_pba_bar(pi) >= 0);
+ b = sc->psc_sel.pc_bus;
+ s = sc->psc_sel.pc_dev;
+ f = sc->psc_sel.pc_func;
+
/*
* If the MSI-X table BAR maps memory intended for
* other uses, it is at least assured that the table
@@ -372,34 +376,44 @@ init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
if (pi->pi_msix.pba_bar == pi->pi_msix.table_bar &&
((pi->pi_msix.pba_offset - pi->pi_msix.table_offset) < 4096)) {
/* Need to also emulate the PBA, not supported yet */
- printf("Unsupported MSI-X configuration: %d/%d/%d\n",
- sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
- sc->psc_sel.pc_func);
+ printf("Unsupported MSI-X configuration: %d/%d/%d\n", b, s, f);
return (-1);
}
- /*
- * May need to split the BAR into 3 regions:
- * Before the MSI-X table, the MSI-X table, and after it
- * XXX for now, assume that the table is not in the middle
- */
+ /* Compute the MSI-X table size */
table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+ table_size = roundup2(table_size, 4096);
+
idx = pi->pi_msix.table_bar;
+ start = pi->pi_bar[idx].addr;
+ remaining = pi->pi_bar[idx].size;
- /* Round up to page size */
- table_size = roundup2(table_size, 4096);
- if (pi->pi_msix.table_offset == 0) {
- /* Map everything after the MSI-X table */
- start = pi->pi_bar[idx].addr + table_size;
- len = pi->pi_bar[idx].size - table_size;
- } else {
- /* Map everything before the MSI-X table */
- start = pi->pi_bar[idx].addr;
+ /* Map everything before the MSI-X table */
+ if (pi->pi_msix.table_offset > 0) {
len = pi->pi_msix.table_offset;
+ error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
+ if (error)
+ return (error);
+
+ base += len;
+ start += len;
+ remaining -= len;
}
- return (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev, sc->psc_sel.pc_func,
- start, len, base + table_size));
+
+ /* Skip the MSI-X table */
+ base += table_size;
+ start += table_size;
+ remaining -= table_size;
+
+ /* Map everything beyond the end of the MSI-X table */
+ if (remaining > 0) {
+ len = remaining;
+ error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
+ if (error)
+ return (error);
+ }
+
+ return (0);
}
static int
OpenPOWER on IntegriCloud