Index: usr.sbin/bhyve/pci_passthru.c =================================================================== --- usr.sbin/bhyve/pci_passthru.c +++ usr.sbin/bhyve/pci_passthru.c @@ -43,7 +43,10 @@ #include #include +#include + #include +#include #ifndef WITHOUT_CAPSICUM #include @@ -79,7 +82,6 @@ #define MSIX_CAPLEN 12 static int pcifd = -1; -static int memfd = -1; struct passthru_softc { struct pci_devinst *psc_pi; @@ -435,13 +437,12 @@ static int init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base) { - int b, s, f; - int idx; - size_t remaining; - uint32_t table_size, table_offset; - uint32_t pba_size, pba_offset; - vm_paddr_t start; struct pci_devinst *pi = sc->psc_pi; + struct pci_bar_mmap pbm; + void *addr; + size_t remaining; + int b, s, f, idx; + uint32_t map_offset, pba_size, pba_offset, table_size, table_offset; assert(pci_msix_table_bar(pi) >= 0 && pci_msix_pba_bar(pi) >= 0); @@ -462,7 +463,6 @@ table_size = roundup2(table_size, 4096); idx = pi->pi_msix.table_bar; - start = pi->pi_bar[idx].addr; remaining = pi->pi_bar[idx].size; if (pi->pi_msix.pba_bar == pi->pi_msix.table_bar) { @@ -477,25 +477,39 @@ pi->pi_msix.pba_page = NULL; pi->pi_msix.pba_page_offset = 0; } else { - /* - * The PBA overlaps with either the first or last - * page of the MSI-X table region. Map the - * appropriate page. - */ - if (pba_offset <= table_offset) - pi->pi_msix.pba_page_offset = table_offset; - else - pi->pi_msix.pba_page_offset = table_offset + - table_size - 4096; - pi->pi_msix.pba_page = mmap(NULL, 4096, PROT_READ | - PROT_WRITE, MAP_SHARED, memfd, start + - pi->pi_msix.pba_page_offset); - if (pi->pi_msix.pba_page == MAP_FAILED) { + memset(&pbm, 0, sizeof(pbm)); + pbm.pbm_sel = sc->psc_sel; + pbm.pbm_flags = PCIIO_BAR_MMAP_RW; + pbm.pbm_reg = PCIR_BAR(pi->pi_msix.pba_bar); + pbm.pbm_memattr = VM_MEMATTR_UNCACHEABLE; + + if (ioctl(pcifd, PCIOCBARMMAP, &pbm) != 0) { warn( "Failed to map PBA page for MSI-X on %d/%d/%d", b, s, f); return (-1); } + + /* + * The PBA overlaps with either the first or last + * page of the MSI-X table region. + */ + assert(pbm.pbm_bar_off == 0); + addr = (void *)(uintptr_t)pbm.pbm_map_base; + if (pba_offset <= table_offset) + map_offset = table_offset; + else + map_offset = table_offset + table_size - 4096; + pi->pi_msix.pba_page = (uint8_t *)addr + map_offset; + pi->pi_msix.pba_page_offset = map_offset; + + /* + * PCIOCBARMMAP maps the entire BAR, remove what we + * don't need. + */ + (void)munmap(addr, map_offset); + (void)munmap((uint8_t *)addr + map_offset + 4096, + pbm.pbm_map_length - (map_offset + 4096)); } } @@ -645,7 +659,7 @@ #ifndef WITHOUT_CAPSICUM cap_rights_t rights; cap_ioctl_t pci_ioctls[] = - { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR, PCIOCBARIO }; + { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR, PCIOCBARIO, PCIOCBARMMAP }; #endif sc = NULL; @@ -676,21 +690,6 @@ errx(EX_OSERR, "Unable to apply rights for sandbox"); #endif - if (memfd < 0) { - memfd = open(_PATH_MEM, O_RDWR, 0); - if (memfd < 0) { - warn("failed to open %s", _PATH_MEM); - return (error); - } - } - -#ifndef WITHOUT_CAPSICUM - cap_rights_clear(&rights, CAP_IOCTL); - cap_rights_set(&rights, CAP_MMAP_RW); - if (caph_rights_limit(memfd, &rights) == -1) - errx(EX_OSERR, "Unable to apply rights for sandbox"); -#endif - #define GET_INT_CONFIG(var, name) do { \ value = get_config_value_node(nvl, name); \ if (value == NULL) { \