diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -56,6 +56,7 @@ /* instance creation */ int (*pe_init)(struct pci_devinst *, nvlist_t *); + int (*pe_teardown)(struct pci_devinst *); int (*pe_legacy_config)(nvlist_t *, const char *); const char *pe_alias; diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -1210,6 +1210,33 @@ return (err); } +#ifdef __amd64__ +/* + * Release all resources held by an emulated PCI device instance. + */ +static void +pci_emul_teardown(struct pci_devinst *pdi) +{ + struct businfo *bi; + struct pcibar *bp; + vmem_t *arena; + int i; + + bi = pci_businfo[pdi->pi_bus]; + for (i = 0; i <= PCI_BARMAX; i++) { + bp = &pdi->pi_bar[i]; + if (bp->type == PCIBAR_NONE) + continue; + unregister_bar(pdi, i); + arena = bi->resources[bp->type]; + assert(arena != NULL); + vmem_free(arena, bp->addr, bp->size); + } + if (pdi->pi_d->pe_teardown != NULL) + (*pdi->pi_d->pe_teardown)(pdi); +} +#endif + void pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr) {