diff options
-rw-r--r-- | sys/amd64/vmm/io/ppt.c | 11 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_passthru.c | 60 |
2 files changed, 47 insertions, 24 deletions
diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index d3ec8d1..4a05985 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -56,9 +56,18 @@ __FBSDID("$FreeBSD$"); /* XXX locking */ #define MAX_PPTDEVS (sizeof(pptdevs) / sizeof(pptdevs[0])) -#define MAX_MMIOSEGS (PCIR_MAX_BAR_0 + 1) #define MAX_MSIMSGS 32 +/* + * If the MSI-X table is located in the middle of a BAR then that MMIO + * region gets split into two segments - one segment above the MSI-X table + * and the other segment below the MSI-X table - with a hole in place of + * the MSI-X table so accesses to it can be trapped and emulated. + * + * So, allocate a MMIO segment for each BAR register + 1 additional segment. + */ +#define MAX_MMIOSEGS ((PCIR_MAX_BAR_0 + 1) + 1) + MALLOC_DEFINE(M_PPTMSIX, "pptmsix", "Passthru MSI-X resources"); struct pptintr_arg { /* pptintr(pptintr_arg) */ 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 |