summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/pci_emul.h9
-rw-r--r--usr.sbin/bhyve/pci_passthru.c38
2 files changed, 32 insertions, 15 deletions
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
index 80a4eac..f007bdf 100644
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -95,8 +95,7 @@ struct msix_table_entry {
* In case the structure is modified to hold extra information, use a define
* for the size that should be emulated.
*/
-#define MSIX_TABLE_ENTRY_SIZE 16
-#define MAX_MSIX_TABLE_SIZE 2048
+#define MSIX_TABLE_ENTRY_SIZE 16
struct pci_devinst {
struct pci_devemu *pi_d;
@@ -121,7 +120,7 @@ struct pci_devinst {
size_t table_offset;
int table_count;
size_t pba_offset;
- struct msix_table_entry table[MAX_MSIX_TABLE_SIZE];
+ struct msix_table_entry *table; /* allocated at runtime */
} pi_msix;
void *pi_arg; /* devemu-private data */
@@ -143,8 +142,8 @@ struct msixcap {
uint8_t capid;
uint8_t nextptr;
uint16_t msgctrl;
- uint32_t table_offset;
- uint32_t pba_offset;
+ uint32_t table_info; /* bar index and offset within it */
+ uint32_t pba_info; /* bar index and offset within it */
} __packed;
void init_pci(struct vmctx *ctx);
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index bc88166..26cf4d1 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
#include <sys/ioctl.h>
#include <dev/io/iodev.h>
+#include <dev/pci/pcireg.h>
+
#include <machine/iodev.h>
#include <stdio.h>
@@ -59,9 +61,7 @@ __FBSDID("$FreeBSD$");
#define LEGACY_SUPPORT 1
-#define MSIX_TABLE_BIR_MASK 7
-#define MSIX_TABLE_OFFSET_MASK (~MSIX_TABLE_BIR_MASK);
-#define MSIX_TABLE_COUNT(x) (((x) & 0x7FF) + 1)
+#define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
#define MSIX_CAPLEN 12
static int pcifd = -1;
@@ -161,7 +161,7 @@ passthru_add_msicap(struct pci_devinst *pi, int msgnum, int nextptr)
static int
cfginitmsi(struct passthru_softc *sc)
{
- int ptr, capptr, cap, sts, caplen;
+ int i, ptr, capptr, cap, sts, caplen, table_size;
uint32_t u32;
struct pcisel sel;
struct pci_devinst *pi;
@@ -220,14 +220,25 @@ cfginitmsi(struct passthru_softc *sc)
if (sc->psc_msix.capoff != 0) {
pi->pi_msix.pba_bar =
- msixcap.pba_offset & MSIX_TABLE_BIR_MASK;
+ msixcap.pba_info & PCIM_MSIX_BIR_MASK;
pi->pi_msix.pba_offset =
- msixcap.pba_offset & MSIX_TABLE_OFFSET_MASK;
+ msixcap.pba_info & ~PCIM_MSIX_BIR_MASK;
pi->pi_msix.table_bar =
- msixcap.table_offset & MSIX_TABLE_BIR_MASK;
+ msixcap.table_info & PCIM_MSIX_BIR_MASK;
pi->pi_msix.table_offset =
- msixcap.table_offset & MSIX_TABLE_OFFSET_MASK;
+ msixcap.table_info & ~PCIM_MSIX_BIR_MASK;
pi->pi_msix.table_count = MSIX_TABLE_COUNT(msixcap.msgctrl);
+
+ /* Allocate the emulated MSI-X table array */
+ table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+ pi->pi_msix.table = malloc(table_size);
+ bzero(pi->pi_msix.table, table_size);
+
+ /* Mask all table entries */
+ for (i = 0; i < pi->pi_msix.table_count; i++) {
+ pi->pi_msix.table[i].vector_control |=
+ PCIM_MSIX_VCTRL_MASK;
+ }
}
#ifdef LEGACY_SUPPORT
@@ -268,9 +279,13 @@ msix_table_read(struct passthru_softc *sc, uint64_t offset, int size)
int index;
pi = sc->psc_pi;
- entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
+
index = offset / MSIX_TABLE_ENTRY_SIZE;
+ if (index >= pi->pi_msix.table_count)
+ return (-1);
+
entry = &pi->pi_msix.table[index];
+ entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
switch(size) {
case 1:
@@ -308,9 +323,12 @@ msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc,
int error, index;
pi = sc->psc_pi;
- entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
index = offset / MSIX_TABLE_ENTRY_SIZE;
+ if (index >= pi->pi_msix.table_count)
+ return;
+
entry = &pi->pi_msix.table[index];
+ entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
/* Only 4 byte naturally-aligned writes are supported */
assert(size == 4);
OpenPOWER on IntegriCloud