diff options
Diffstat (limited to 'usr.sbin/bhyve/pci_emul.c')
-rw-r--r-- | usr.sbin/bhyve/pci_emul.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index 32a3deb..cb09b7c 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -740,6 +740,38 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, CFGWRITE(pi, offset, val, bytes); } +void +pciecap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, + int bytes, uint32_t val) +{ + + /* XXX don't write to the readonly parts */ + CFGWRITE(pi, offset, val, bytes); +} + +#define PCIECAP_VERSION 0x2 +int +pci_emul_add_pciecap(struct pci_devinst *pi, int type) +{ + int err; + struct pciecap pciecap; + + CTASSERT(sizeof(struct pciecap) == 60); + + if (type != PCIEM_TYPE_ROOT_PORT) + return (-1); + + bzero(&pciecap, sizeof(pciecap)); + + pciecap.capid = PCIY_EXPRESS; + pciecap.pcie_capabilities = PCIECAP_VERSION | PCIEM_TYPE_ROOT_PORT; + pciecap.link_capabilities = 0x411; /* gen1, x1 */ + pciecap.link_status = 0x11; /* gen1, x1 */ + + err = pci_emul_add_capability(pi, (u_char *)&pciecap, sizeof(pciecap)); + return (err); +} + /* * This function assumes that 'coff' is in the capabilities region of the * config space. @@ -782,6 +814,9 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val) case PCIY_MSIX: msixcap_cfgwrite(pi, capoff, offset, bytes, val); break; + case PCIY_EXPRESS: + pciecap_cfgwrite(pi, capoff, offset, bytes, val); + break; default: break; } @@ -811,12 +846,29 @@ pci_emul_iscap(struct pci_devinst *pi, int offset) return (found); } +static int +pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr, + int size, uint64_t *val, void *arg1, long arg2) +{ + /* + * Ignore writes; return 0xff's for reads. The mem read code + * will take care of truncating to the correct size. + */ + if (dir == MEM_F_READ) { + *val = 0xffffffffffffffff; + } + + return (0); +} + void init_pci(struct vmctx *ctx) { + struct mem_range memp; struct pci_devemu *pde; struct slotinfo *si; int slot, func; + int error; pci_emul_iobase = PCI_EMUL_IOBASE; pci_emul_membase32 = PCI_EMUL_MEMBASE32; @@ -844,6 +896,20 @@ init_pci(struct vmctx *ctx) lirq[11].li_generic = 1; lirq[12].li_generic = 1; lirq[15].li_generic = 1; + + /* + * Setup the PCI hole to return 0xff's when accessed in a region + * with no devices + */ + memset(&memp, 0, sizeof(struct mem_range)); + memp.name = "PCI hole"; + memp.flags = MEM_F_RW; + memp.base = lomem_sz; + memp.size = (4ULL * 1024 * 1024 * 1024) - lomem_sz; + memp.handler = pci_emul_fallback_handler; + + error = register_mem_fallback(&memp); + assert(error == 0); } int |