diff options
Diffstat (limited to 'usr.sbin/bhyve/pci_emul.c')
-rw-r--r-- | usr.sbin/bhyve/pci_emul.c | 74 |
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) |