summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-02-01 02:41:47 +0000
committerneel <neel@FreeBSD.org>2013-02-01 02:41:47 +0000
commit803db8c37c2516174b23103ab861a500599042dc (patch)
tree1ac97e1077d1065ad76a96893001e6ea94de8ada /usr.sbin
parentc9a45ab898c8adbadbd15cf73d00a9dbf1d4ba52 (diff)
downloadFreeBSD-src-803db8c37c2516174b23103ab861a500599042dc.zip
FreeBSD-src-803db8c37c2516174b23103ab861a500599042dc.tar.gz
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
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/pci_emul.c20
-rw-r--r--usr.sbin/bhyve/pci_emul.h2
-rw-r--r--usr.sbin/bhyve/pci_passthru.c12
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c8
4 files changed, 34 insertions, 8 deletions
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));
}
}
OpenPOWER on IntegriCloud