From 803db8c37c2516174b23103ab861a500599042dc Mon Sep 17 00:00:00 2001 From: neel Date: Fri, 1 Feb 2013 02:41:47 +0000 Subject: Fix a bug in the passthru implementation where it would assume that all devices are MSI-X capable. This in turn would lead it to treat bar 0 as the MSI-X table bar even if the underlying device did not support MSI-X. Fix this by providing an API to query the MSI-X table index of the emulated device. If the underlying device does not support MSI-X then this API will return -1. Obtained from: NetApp --- usr.sbin/bhyve/pci_emul.c | 20 ++++++++++++++++++++ usr.sbin/bhyve/pci_emul.h | 2 ++ usr.sbin/bhyve/pci_passthru.c | 12 ++++++++---- usr.sbin/bhyve/pci_virtio_net.c | 8 ++++---- 4 files changed, 34 insertions(+), 8 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index d6315cf..32a3deb 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -254,6 +254,26 @@ pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size) return (retval); } +int +pci_msix_table_bar(struct pci_devinst *pi) +{ + + if (pi->pi_msix.table != NULL) + return (pi->pi_msix.table_bar); + else + return (-1); +} + +int +pci_msix_pba_bar(struct pci_devinst *pi) +{ + + if (pi->pi_msix.table != NULL) + return (pi->pi_msix.pba_bar); + else + return (-1); +} + static int pci_emul_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, uint32_t *eax, void *arg) diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index 5338aec..8c6260c 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -169,6 +169,8 @@ void pci_lintr_deassert(struct pci_devinst *pi); int pci_lintr_request(struct pci_devinst *pi, int ivec); int pci_msi_enabled(struct pci_devinst *pi); int pci_msix_enabled(struct pci_devinst *pi); +int pci_msix_table_bar(struct pci_devinst *pi); +int pci_msix_pba_bar(struct pci_devinst *pi); int pci_msi_msgnum(struct pci_devinst *pi); void pci_parse_slot(char *opt, int legacy); void pci_populate_msicap(struct msicap *cap, int msgs, int nextptr); diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c index 26cf4d1..131f08a 100644 --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -361,6 +361,8 @@ init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base) size_t len; struct pci_devinst *pi = sc->psc_pi; + assert(pci_msix_table_bar(pi) >= 0 && pci_msix_pba_bar(pi) >= 0); + /* * If the MSI-X table BAR maps memory intended for * other uses, it is at least assured that the table @@ -370,7 +372,9 @@ 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 table and PBA in same page\n"); + printf("Unsupported MSI-X configuration: %d/%d/%d\n", + sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, + sc->psc_sel.pc_func); return (-1); } @@ -447,7 +451,7 @@ cfginitbar(struct vmctx *ctx, struct passthru_softc *sc) return (-1); /* The MSI-X table needs special handling */ - if (i == pi->pi_msix.table_bar) { + if (i == pci_msix_table_bar(pi)) { error = init_msix_table(ctx, sc, base); if (error) return (-1); @@ -688,7 +692,7 @@ passthru_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, sc = pi->pi_arg; - if (pi->pi_msix.table_bar == baridx) { + if (baridx == pci_msix_table_bar(pi)) { msix_table_write(ctx, vcpu, sc, offset, size, value); } else { assert(pi->pi_bar[baridx].type == PCIBAR_IO); @@ -712,7 +716,7 @@ passthru_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, sc = pi->pi_arg; - if (pi->pi_msix.table_bar == baridx) { + if (baridx == pci_msix_table_bar(pi)) { val = msix_table_read(sc, offset, size); } else { assert(pi->pi_bar[baridx].type == PCIBAR_IO); diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c index 444e0e5..327ebf7 100644 --- a/usr.sbin/bhyve/pci_virtio_net.c +++ b/usr.sbin/bhyve/pci_virtio_net.c @@ -685,8 +685,8 @@ pci_vtnet_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, void *ptr; if (use_msix) { - if (baridx == pi->pi_msix.table_bar || - baridx == pi->pi_msix.pba_bar) { + if (baridx == pci_msix_table_bar(pi) || + baridx == pci_msix_pba_bar(pi)) { pci_emul_msix_twrite(pi, offset, size, value); return; } @@ -781,8 +781,8 @@ pci_vtnet_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, uint64_t value; if (use_msix) { - if (baridx == pi->pi_msix.table_bar || - baridx == pi->pi_msix.pba_bar) { + if (baridx == pci_msix_table_bar(pi) || + baridx == pci_msix_pba_bar(pi)) { return (pci_emul_msix_tread(pi, offset, size)); } } -- cgit v1.1