Lines Matching +full:msi +full:- +full:offset
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
78 static int pcifd = -1;
117 len = 10; /* minimum length of msi capability */ in msi_caplen()
124 * Ignore the 'mask' and 'pending' bits in the MSI capability. in msi_caplen()
142 return (-1); in pcifd_open()
157 if (caph_rights_limit(pcifd, &pcifd_rights) == -1) in pcifd_init()
162 if (caph_ioctls_limit(pcifd, pcifd_ioctls, nitems(pcifd_ioctls)) == -1) in pcifd_init()
252 * Copy the msi capability structure in the last 16 bytes of the in passthru_add_msicap()
256 capoff = 256 - roundup(sizeof(msicap), 4); in passthru_add_msicap()
275 pi = sc->psc_pi; in cfginitmsi()
276 sel = sc->psc_sel; in cfginitmsi()
279 * Parse the capabilities and cache the location of the MSI in cfginitmsi()
280 * and MSI-X capabilities. in cfginitmsi()
289 * Copy the MSI capability into the config in cfginitmsi()
292 sc->psc_msi.capoff = ptr; in cfginitmsi()
293 sc->psc_msi.msgctrl = in cfginitmsi()
295 sc->psc_msi.emulated = 0; in cfginitmsi()
296 caplen = msi_caplen(sc->psc_msi.msgctrl); in cfginitmsi()
302 caplen -= 4; in cfginitmsi()
307 * Copy the MSI-X capability in cfginitmsi()
309 sc->psc_msix.capoff = ptr; in cfginitmsi()
318 caplen -= 4; in cfginitmsi()
328 if (sc->psc_msix.capoff != 0) { in cfginitmsi()
329 pi->pi_msix.pba_bar = in cfginitmsi()
331 pi->pi_msix.pba_offset = in cfginitmsi()
333 pi->pi_msix.table_bar = in cfginitmsi()
335 pi->pi_msix.table_offset = in cfginitmsi()
337 pi->pi_msix.table_count = MSIX_TABLE_COUNT(msixcap.msgctrl); in cfginitmsi()
338 pi->pi_msix.pba_size = PBA_SIZE(pi->pi_msix.table_count); in cfginitmsi()
340 /* Allocate the emulated MSI-X table array */ in cfginitmsi()
341 table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE; in cfginitmsi()
342 pi->pi_msix.table = calloc(1, table_size); in cfginitmsi()
345 for (i = 0; i < pi->pi_msix.table_count; i++) { in cfginitmsi()
346 pi->pi_msix.table[i].vector_control |= in cfginitmsi()
353 * If the passthrough device does not support MSI then craft a in cfginitmsi()
354 * MSI capability for it. We link the new MSI capability at the in cfginitmsi()
357 if ((sts & PCIM_STATUS_CAPPRESENT) != 0 && sc->psc_msi.capoff == 0) { in cfginitmsi()
361 sc->psc_msi.capoff = msiptr; in cfginitmsi()
362 sc->psc_msi.msgctrl = pci_get_cfgdata16(pi, msiptr + 2); in cfginitmsi()
363 sc->psc_msi.emulated = 1; in cfginitmsi()
369 if (sc->psc_msi.capoff == 0 && sc->psc_msix.capoff == 0) in cfginitmsi()
370 return (-1); in cfginitmsi()
376 msix_table_read(struct passthru_softc *sc, uint64_t offset, int size) in msix_table_read() argument
389 pi = sc->psc_pi; in msix_table_read()
391 table_offset = pi->pi_msix.table_offset; in msix_table_read()
392 table_count = pi->pi_msix.table_count; in msix_table_read()
393 if (offset < table_offset || in msix_table_read()
394 offset >= table_offset + table_count * MSIX_TABLE_ENTRY_SIZE) { in msix_table_read()
397 src8 = (uint8_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_read()
401 src16 = (uint16_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_read()
405 src32 = (uint32_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_read()
409 src64 = (uint64_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_read()
413 return (-1); in msix_table_read()
418 offset -= table_offset; in msix_table_read()
419 index = offset / MSIX_TABLE_ENTRY_SIZE; in msix_table_read()
422 entry = &pi->pi_msix.table[index]; in msix_table_read()
423 entry_offset = offset % MSIX_TABLE_ENTRY_SIZE; in msix_table_read()
443 return (-1); in msix_table_read()
450 msix_table_write(struct passthru_softc *sc, uint64_t offset, int size, in msix_table_write() argument
463 pi = sc->psc_pi; in msix_table_write()
465 table_offset = pi->pi_msix.table_offset; in msix_table_write()
466 table_count = pi->pi_msix.table_count; in msix_table_write()
467 if (offset < table_offset || in msix_table_write()
468 offset >= table_offset + table_count * MSIX_TABLE_ENTRY_SIZE) { in msix_table_write()
471 dest8 = (uint8_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_write()
475 dest16 = (uint16_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_write()
479 dest32 = (uint32_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_write()
483 dest64 = (uint64_t *)(pi->pi_msix.mapped_addr + offset); in msix_table_write()
490 offset -= table_offset; in msix_table_write()
491 index = offset / MSIX_TABLE_ENTRY_SIZE; in msix_table_write()
494 entry = &pi->pi_msix.table[index]; in msix_table_write()
495 entry_offset = offset % MSIX_TABLE_ENTRY_SIZE; in msix_table_write()
497 /* Only 4 byte naturally-aligned writes are supported */ in msix_table_write()
501 vector_control = entry->vector_control; in msix_table_write()
504 /* If MSI-X hasn't been enabled, do nothing */ in msix_table_write()
505 if (pi->pi_msix.enabled) { in msix_table_write()
507 if ((entry->vector_control & PCIM_MSIX_VCTRL_MASK) == 0 || in msix_table_write()
509 (void)vm_setup_pptdev_msix(sc->psc_pi->pi_vmctx, in msix_table_write()
510 sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, in msix_table_write()
511 sc->psc_sel.pc_func, index, entry->addr, in msix_table_write()
512 entry->msg_data, entry->vector_control); in msix_table_write()
520 struct pci_devinst *pi = sc->psc_pi; in init_msix_table()
527 b = sc->psc_sel.pc_bus; in init_msix_table()
528 s = sc->psc_sel.pc_dev; in init_msix_table()
529 f = sc->psc_sel.pc_func; in init_msix_table()
532 * Map the region of the BAR containing the MSI-X table. This is in init_msix_table()
534 * 1. The PBA may reside in the first or last page containing the MSI-X in init_msix_table()
537 * the MSI-X table for other purposes, some do in practice. in init_msix_table()
540 pbm.pbm_sel = sc->psc_sel; in init_msix_table()
542 pbm.pbm_reg = PCIR_BAR(pi->pi_msix.table_bar); in init_msix_table()
546 warn("Failed to map MSI-X table BAR on %d/%d/%d", b, s, f); in init_msix_table()
547 return (-1); in init_msix_table()
550 pi->pi_msix.mapped_addr = (uint8_t *)(uintptr_t)pbm.pbm_map_base; in init_msix_table()
551 pi->pi_msix.mapped_size = pbm.pbm_map_length; in init_msix_table()
553 table_offset = rounddown2(pi->pi_msix.table_offset, 4096); in init_msix_table()
555 table_size = pi->pi_msix.table_offset - table_offset; in init_msix_table()
556 table_size += pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE; in init_msix_table()
562 * a buggy out-of-bounds access causes a crash. in init_msix_table()
565 if (mprotect(pi->pi_msix.mapped_addr, table_offset, in init_msix_table()
567 warn("Failed to unmap MSI-X table BAR region"); in init_msix_table()
568 if (table_offset + table_size != pi->pi_msix.mapped_size) in init_msix_table()
570 pi->pi_msix.mapped_addr + table_offset + table_size, in init_msix_table()
571 pi->pi_msix.mapped_size - (table_offset + table_size), in init_msix_table()
573 warn("Failed to unmap MSI-X table BAR region"); in init_msix_table()
587 pi = sc->psc_pi; in cfginitbar()
596 bar.pbi_sel = sc->psc_sel; in cfginitbar()
622 sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, in cfginitbar()
623 sc->psc_sel.pc_func, i, base, size); in cfginitbar()
624 return (-1); in cfginitbar()
629 sc->psc_bar[i].type = bartype; in cfginitbar()
630 sc->psc_bar[i].size = size; in cfginitbar()
631 sc->psc_bar[i].addr = base; in cfginitbar()
632 sc->psc_bar[i].lobits = 0; in cfginitbar()
637 return (-1); in cfginitbar()
640 lobits = (uint8_t)passthru_read_config(&sc->psc_sel, in cfginitbar()
647 sc->psc_bar[i].lobits = lobits; in cfginitbar()
648 pi->pi_bar[i].lobits = lobits; in cfginitbar()
651 * 64-bit BAR takes up two slots so skip the next one. in cfginitbar()
656 sc->psc_bar[i].type = PCIBAR_MEMHI64; in cfginitbar()
671 sc = pi->pi_arg; in cfginit()
673 bzero(&sc->psc_sel, sizeof(struct pcisel)); in cfginit()
674 sc->psc_sel.pc_bus = bus; in cfginit()
675 sc->psc_sel.pc_dev = slot; in cfginit()
676 sc->psc_sel.pc_func = func; in cfginit()
688 passthru_read_config(&sc->psc_sel, i, 4)); in cfginit()
695 warnx("failed to initialize MSI for PCI %d/%d/%d", in cfginit()
710 "failed to initialize MSI-X table for PCI %d/%d/%d: %d", in cfginit()
727 return (&sc->psc_mmio_map[num]); in passthru_get_mmio()
735 return (&sc->psc_sel); in passthru_get_sel()
743 return (-1); in set_pcir_handler()
746 assert(sc->psc_pcir_rhandler[i] == NULL || rhandler == NULL); in set_pcir_handler()
747 assert(sc->psc_pcir_whandler[i] == NULL || whandler == NULL); in set_pcir_handler()
748 sc->psc_pcir_rhandler[i] = rhandler; in set_pcir_handler()
749 sc->psc_pcir_whandler[i] = whandler; in set_pcir_handler()
763 assert(sc->psc_bar[baridx].type == PCIBAR_IO || in passthru_set_bar_handler()
764 sc->psc_bar[baridx].type == PCIBAR_MEM32 || in passthru_set_bar_handler()
765 sc->psc_bar[baridx].type == PCIBAR_MEM64); in passthru_set_bar_handler()
766 assert(sc->psc_bar[baridx].size >= off + size); in passthru_set_bar_handler()
774 handler_new->off = off; in passthru_set_bar_handler()
775 handler_new->size = size; in passthru_set_bar_handler()
776 handler_new->read = rhandler; in passthru_set_bar_handler()
777 handler_new->write = whandler; in passthru_set_bar_handler()
779 TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) { in passthru_set_bar_handler()
780 if (handler->off < handler_new->off) { in passthru_set_bar_handler()
781 assert(handler->off + handler->size < handler_new->off); in passthru_set_bar_handler()
784 assert(handler->off > handler_new->off + handler_new->size); in passthru_set_bar_handler()
789 TAILQ_INSERT_TAIL(&sc->psc_bar_handler[baridx], handler_new, chain); in passthru_set_bar_handler()
808 tofree = strndup(opts, cp - opts); in passthru_legacy_config()
822 return (-1); in passthru_legacy_config()
842 return (-1); in passthru_init_rom()
849 return (-1); in passthru_init_rom()
859 return (-1); in passthru_init_rom()
863 int error = pci_emul_alloc_rom(sc->psc_pi, rom_size, &rom_addr); in passthru_init_rom()
872 sc->psc_bar[PCI_ROM_IDX].type = PCIBAR_ROM; in passthru_init_rom()
873 sc->psc_bar[PCI_ROM_IDX].addr = (uint64_t)rom_addr; in passthru_init_rom()
874 sc->psc_bar[PCI_ROM_IDX].size = rom_size; in passthru_init_rom()
903 while (cp != name && isdigit(cp[-1])) in passthru_lookup_pptdev()
904 cp--; in passthru_lookup_pptdev()
909 if ((size_t)(cp - name) + 1 > sizeof(patterns[0].pd_name)) { in passthru_lookup_pptdev()
913 memcpy(patterns[0].pd_name, name, cp - name); in passthru_lookup_pptdev()
924 if (ioctl(pcifd, PCIOCGETCONF, &pc) == -1) { in passthru_lookup_pptdev()
960 memflags = vm_get_memflags(pi->pi_vmctx); in passthru_init()
989 if (vm_assign_pptdev(pi->pi_vmctx, bus, slot, func) != 0) { in passthru_init()
997 pi->pi_arg = sc; in passthru_init()
998 sc->psc_pi = pi; in passthru_init()
1001 TAILQ_INIT(&sc->psc_bar_handler[i]); in passthru_init()
1023 assert(devp->probe != NULL); in passthru_init()
1024 if (devp->probe(pi) == 0) { in passthru_init()
1031 error = dev->init(pi, nvl); in passthru_init()
1040 dev->deinit(pi); in passthru_init()
1042 vm_unassign_pptdev(pi->pi_vmctx, bus, slot, func); in passthru_init()
1052 if (sc->psc_msi.capoff == 0) in msicap_access()
1055 caplen = msi_caplen(sc->psc_msi.msgctrl); in msicap_access()
1057 if (coff >= sc->psc_msi.capoff && coff < sc->psc_msi.capoff + caplen) in msicap_access()
1066 if (sc->psc_msix.capoff == 0) in msixcap_access()
1069 return (coff >= sc->psc_msix.capoff && in msixcap_access()
1070 coff < sc->psc_msix.capoff + MSIX_CAPLEN); in msixcap_access()
1078 * MSI capability is emulated. in passthru_cfgread_default()
1081 return (-1); in passthru_cfgread_default()
1092 return (-1); in passthru_cfgread_default()
1093 st = passthru_read_config(&sc->psc_sel, PCIR_STATUS, 2); in passthru_cfgread_default()
1099 *rv = passthru_read_config(&sc->psc_sel, coff, bytes); in passthru_cfgread_default()
1109 return (-1); in passthru_cfgread_emulate()
1117 sc = pi->pi_arg; in passthru_cfgread()
1119 if (sc->psc_pcir_rhandler[coff] != NULL) in passthru_cfgread()
1120 return (sc->psc_pcir_rhandler[coff](sc, pi, coff, bytes, rv)); in passthru_cfgread()
1133 * MSI capability is emulated in passthru_cfgwrite_default()
1136 pci_emul_capwrite(pi, coff, bytes, val, sc->psc_msi.capoff, in passthru_cfgwrite_default()
1138 error = vm_setup_pptdev_msi(pi->pi_vmctx, sc->psc_sel.pc_bus, in passthru_cfgwrite_default()
1139 sc->psc_sel.pc_dev, sc->psc_sel.pc_func, in passthru_cfgwrite_default()
1140 pi->pi_msi.addr, pi->pi_msi.msg_data, in passthru_cfgwrite_default()
1141 pi->pi_msi.maxmsgnum); in passthru_cfgwrite_default()
1148 pci_emul_capwrite(pi, coff, bytes, val, sc->psc_msix.capoff, in passthru_cfgwrite_default()
1150 if (pi->pi_msix.enabled) { in passthru_cfgwrite_default()
1151 msix_table_entries = pi->pi_msix.table_count; in passthru_cfgwrite_default()
1153 error = vm_setup_pptdev_msix(pi->pi_vmctx, in passthru_cfgwrite_default()
1154 sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, in passthru_cfgwrite_default()
1155 sc->psc_sel.pc_func, i, in passthru_cfgwrite_default()
1156 pi->pi_msix.table[i].addr, in passthru_cfgwrite_default()
1157 pi->pi_msix.table[i].msg_data, in passthru_cfgwrite_default()
1158 pi->pi_msix.table[i].vector_control); in passthru_cfgwrite_default()
1164 error = vm_disable_pptdev_msix(pi->pi_vmctx, in passthru_cfgwrite_default()
1165 sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, in passthru_cfgwrite_default()
1166 sc->psc_sel.pc_func); in passthru_cfgwrite_default()
1179 return (-1); in passthru_cfgwrite_default()
1182 passthru_write_config(&sc->psc_sel, PCIR_STATUS, val >> 16, 2); in passthru_cfgwrite_default()
1191 passthru_write_config(&sc->psc_sel, coff, bytes, val); in passthru_cfgwrite_default()
1201 return (-1); in passthru_cfgwrite_emulate()
1209 sc = pi->pi_arg; in passthru_cfgwrite()
1211 if (sc->psc_pcir_whandler[coff] != NULL) in passthru_cfgwrite()
1212 return (sc->psc_pcir_whandler[coff](sc, pi, coff, bytes, val)); in passthru_cfgwrite()
1218 passthru_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size, in passthru_write() argument
1225 sc = pi->pi_arg; in passthru_write()
1228 msix_table_write(sc, offset, size, value); in passthru_write()
1232 TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) { in passthru_write()
1233 if (offset >= handler->off + handler->size) { in passthru_write()
1235 } else if (offset < handler->off) { in passthru_write()
1236 assert(offset + size < handler->off); in passthru_write()
1240 * offset. in passthru_write()
1245 assert(offset + size <= handler->off + handler->size); in passthru_write()
1247 handler->write(pi, baridx, in passthru_write()
1248 offset - handler->off, size, value); in passthru_write()
1253 pio.pbi_sel = sc->psc_sel; in passthru_write()
1256 pio.pbi_offset = (uint32_t)offset; in passthru_write()
1265 passthru_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size) in passthru_read() argument
1272 sc = pi->pi_arg; in passthru_read()
1275 val = msix_table_read(sc, offset, size); in passthru_read()
1279 TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) { in passthru_read()
1280 if (offset >= handler->off + handler->size) { in passthru_read()
1282 } else if (offset < handler->off) { in passthru_read()
1283 assert(offset + size < handler->off); in passthru_read()
1287 * offset. in passthru_read()
1292 assert(offset + size <= handler->off + handler->size); in passthru_read()
1294 return (handler->read(pi, baridx, in passthru_read()
1295 offset - handler->off, size)); in passthru_read()
1299 pio.pbi_sel = sc->psc_sel; in passthru_read()
1302 pio.pbi_offset = (uint32_t)offset; in passthru_read()
1321 sc = pi->pi_arg; in passthru_msix_addr()
1322 table_offset = rounddown2(pi->pi_msix.table_offset, 4096); in passthru_msix_addr()
1325 if (vm_unmap_pptdev_mmio(pi->pi_vmctx, in passthru_msix_addr()
1326 sc->psc_sel.pc_bus, in passthru_msix_addr()
1327 sc->psc_sel.pc_dev, in passthru_msix_addr()
1328 sc->psc_sel.pc_func, address, in passthru_msix_addr()
1332 if (vm_map_pptdev_mmio(pi->pi_vmctx, sc->psc_sel.pc_bus, in passthru_msix_addr()
1333 sc->psc_sel.pc_dev, in passthru_msix_addr()
1334 sc->psc_sel.pc_func, address, in passthru_msix_addr()
1336 sc->psc_bar[baridx].addr) != 0) in passthru_msix_addr()
1340 table_size = pi->pi_msix.table_offset - table_offset; in passthru_msix_addr()
1341 table_size += pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE; in passthru_msix_addr()
1343 remaining = pi->pi_bar[baridx].size - table_offset - table_size; in passthru_msix_addr()
1347 if (vm_unmap_pptdev_mmio(pi->pi_vmctx, in passthru_msix_addr()
1348 sc->psc_sel.pc_bus, in passthru_msix_addr()
1349 sc->psc_sel.pc_dev, in passthru_msix_addr()
1350 sc->psc_sel.pc_func, address, in passthru_msix_addr()
1354 if (vm_map_pptdev_mmio(pi->pi_vmctx, sc->psc_sel.pc_bus, in passthru_msix_addr()
1355 sc->psc_sel.pc_dev, in passthru_msix_addr()
1356 sc->psc_sel.pc_func, address, in passthru_msix_addr()
1358 sc->psc_bar[baridx].addr + in passthru_msix_addr()
1371 sc = pi->pi_arg; in passthru_mmio_map()
1373 if (vm_unmap_pptdev_mmio(pi->pi_vmctx, sc->psc_sel.pc_bus, in passthru_mmio_map()
1374 sc->psc_sel.pc_dev, sc->psc_sel.pc_func, address + off, in passthru_mmio_map()
1377 return (-1); in passthru_mmio_map()
1380 if (vm_map_pptdev_mmio(pi->pi_vmctx, sc->psc_sel.pc_bus, in passthru_mmio_map()
1381 sc->psc_sel.pc_dev, sc->psc_sel.pc_func, address + off, in passthru_mmio_map()
1382 size, sc->psc_bar[baridx].addr + off) != 0) { in passthru_mmio_map()
1384 return (-1); in passthru_mmio_map()
1399 sc = pi->pi_arg; in passthru_mmio_addr()
1403 /* The queue is sorted by offset in ascending order. */ in passthru_mmio_addr()
1404 TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) { in passthru_mmio_addr()
1405 uint64_t handler_off = trunc_page(handler->off); in passthru_mmio_addr()
1406 uint64_t handler_end = round_page(handler->off + handler->size); in passthru_mmio_addr()
1415 handler_off - off); in passthru_mmio_addr()
1422 sc->psc_bar[baridx].size - off); in passthru_mmio_addr()
1429 const uint64_t addr = pi->pi_bar[idx].addr; in passthru_addr_rom()
1430 const uint64_t size = pi->pi_bar[idx].size; in passthru_addr_rom()
1433 if (vm_munmap_memseg(pi->pi_vmctx, addr, size) != 0) { in passthru_addr_rom()
1434 errx(4, "%s: munmap_memseg @ [%016lx - %016lx] failed", in passthru_addr_rom()
1439 if (vm_mmap_memseg(pi->pi_vmctx, addr, VM_PCIROM, in passthru_addr_rom()
1440 pi->pi_romoffset, size, PROT_READ | PROT_EXEC) != 0) { in passthru_addr_rom()
1441 errx(4, "%s: mmap_memseg @ [%016lx - %016lx] failed", in passthru_addr_rom()
1450 switch (pi->pi_bar[baridx].type) { in passthru_addr()
1466 pi->pi_bar[baridx].type); in passthru_addr()