summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/pci_emul.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bhyve/pci_emul.c')
-rw-r--r--usr.sbin/bhyve/pci_emul.c74
1 files changed, 44 insertions, 30 deletions
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index 37f1778..00adf62 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -47,13 +47,14 @@ __FBSDID("$FreeBSD$");
#include "bhyverun.h"
#include "inout.h"
#include "mem.h"
-#include "mptbl.h"
#include "pci_emul.h"
#include "ioapic.h"
#define CONF1_ADDR_PORT 0x0cf8
#define CONF1_DATA_PORT 0x0cfc
+#define CONF1_ENABLE 0x80000000ul
+
#define CFGWRITE(pi,off,val,b) \
do { \
if ((b) == 1) { \
@@ -139,20 +140,15 @@ pci_parse_slot(char *opt, int legacy)
error = -1;
str = cpy = strdup(opt);
- config = NULL;
-
- if (strchr(str, ':') != NULL) {
- slot = strsep(&str, ":");
- func = strsep(&str, ",");
- } else {
- slot = strsep(&str, ",");
- func = NULL;
- }
-
+ slot = strsep(&str, ",");
+ func = NULL;
+ if (strchr(slot, ':') != NULL) {
+ func = cpy;
+ (void) strsep(&func, ":");
+ }
+
emul = strsep(&str, ",");
- if (str != NULL) {
- config = strsep(&str, ",");
- }
+ config = str;
if (emul == NULL) {
pci_parse_slot_usage(opt);
@@ -666,11 +662,13 @@ pci_emul_finddev(char *name)
return (NULL);
}
-static void
+static int
pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
char *params)
{
struct pci_devinst *pdi;
+ int err;
+
pdi = malloc(sizeof(struct pci_devinst));
bzero(pdi, sizeof(*pdi));
@@ -688,12 +686,15 @@ pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
pci_set_cfgdata8(pdi, PCIR_COMMAND,
PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
- if ((*pde->pe_init)(ctx, pdi, params) != 0) {
+ err = (*pde->pe_init)(ctx, pdi, params);
+ if (err != 0) {
free(pdi);
} else {
pci_emul_devices++;
pci_slotinfo[slot][func].si_devi = pdi;
- }
+ }
+
+ return (err);
}
void
@@ -993,7 +994,7 @@ pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
return (0);
}
-void
+int
init_pci(struct vmctx *ctx)
{
struct mem_range memp;
@@ -1013,8 +1014,10 @@ init_pci(struct vmctx *ctx)
if (si->si_name != NULL) {
pde = pci_emul_finddev(si->si_name);
assert(pde != NULL);
- pci_emul_init(ctx, pde, slot, func,
- si->si_param);
+ error = pci_emul_init(ctx, pde, slot, func,
+ si->si_param);
+ if (error)
+ return (error);
}
}
}
@@ -1051,6 +1054,8 @@ init_pci(struct vmctx *ctx)
error = register_mem_fallback(&memp);
assert(error == 0);
+
+ return (0);
}
int
@@ -1224,20 +1229,29 @@ pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
{
uint32_t x;
- assert(!in);
-
- if (bytes != 4)
- return (-1);
+ if (bytes != 4) {
+ if (in)
+ *eax = (bytes == 2) ? 0xffff : 0xff;
+ return (0);
+ }
- x = *eax;
- cfgoff = x & PCI_REGMAX;
- cfgfunc = (x >> 8) & PCI_FUNCMAX;
- cfgslot = (x >> 11) & PCI_SLOTMAX;
- cfgbus = (x >> 16) & PCI_BUSMAX;
+ if (in) {
+ x = (cfgbus << 16) |
+ (cfgslot << 11) |
+ (cfgfunc << 8) |
+ cfgoff;
+ *eax = x | CONF1_ENABLE;
+ } else {
+ x = *eax;
+ cfgoff = x & PCI_REGMAX;
+ cfgfunc = (x >> 8) & PCI_FUNCMAX;
+ cfgslot = (x >> 11) & PCI_SLOTMAX;
+ cfgbus = (x >> 16) & PCI_BUSMAX;
+ }
return (0);
}
-INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_OUT, pci_emul_cfgaddr);
+INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_INOUT, pci_emul_cfgaddr);
static uint32_t
bits_changed(uint32_t old, uint32_t new, uint32_t mask)
OpenPOWER on IntegriCloud