/* Select the MSI-X vectors used by device. * ivshmem maps events to vectors statically, so * we just enable all vectors on init and after reset. */ static void ivshmem_use_msix(IVShmemState * s) { PCIDevice *d = PCI_DEVICE(s); int i; IVSHMEM_DPRINTF("%s, msix present: %d\n", __func__, msix_present(d)); if (!msix_present(d)) { return; } for (i = 0; i < s->vectors; i++) { msix_vector_use(d, i); } }
void msix_unuse_all_vectors(PCIDevice *dev) { if (!msix_present(dev)) { return; } msix_free_irq_entries(dev); }
void msix_uninit_exclusive_bar(PCIDevice *dev) { if (msix_present(dev)) { msix_uninit(dev, &dev->msix_exclusive_bar, &dev->msix_exclusive_bar); memory_region_destroy(&dev->msix_exclusive_bar); } }
/* Handle MSI-X capability config write. */ void msix_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) { unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET; int vector; bool was_masked; if (!msix_present(dev) || !range_covers_byte(addr, len, enable_pos)) { return; } was_masked = dev->msix_function_masked; msix_update_function_masked(dev); if (!msix_enabled(dev)) { return; } pci_device_deassert_intx(dev); if (dev->msix_function_masked == was_masked) { return; } for (vector = 0; vector < dev->msix_entries_nr; ++vector) { msix_handle_mask_update(dev, vector, msix_vector_masked(dev, vector, was_masked)); } }
void msix_save(PCIDevice *dev, QEMUFile *f) { unsigned n = dev->msix_entries_nr; if (!msix_present(dev)) { return; } qemu_put_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE); qemu_put_buffer(f, dev->msix_pba, (n + 7) / 8); }
/* Select the MSI-X vectors used by device. * ivshmem maps events to vectors statically, so * we just enable all vectors on init and after reset. */ static void ivshmem_use_msix(IVShmemState * s) { int i; if (!msix_present(&s->dev)) { return; } for (i = 0; i < s->vectors; i++) { msix_vector_use(&s->dev, i); } }
void msix_reset(PCIDevice *dev) { if (!msix_present(dev)) { return; } msix_clear_all_vectors(dev); dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &= ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET]; memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE); memset(dev->msix_pba, 0, QEMU_ALIGN_UP(dev->msix_entries_nr, 64) / 8); msix_mask_all(dev, dev->msix_entries_nr); }
/* Select the MSI-X vectors used by device. * ivshmem maps events to vectors statically, so * we just enable all vectors on init and after reset. */ static void ivshmem_use_msix(IVShmemState * s) { PCIDevice *d = PCI_DEVICE(s); int i; if (!msix_present(d)) { return; } for (i = 0; i < s->vectors; i++) { msix_vector_use(d, i); } }
/* Should be called after restoring the config space. */ void msix_load(PCIDevice *dev, QEMUFile *f) { unsigned n = dev->msix_entries_nr; unsigned int vector; if (!msix_present(dev)) { return; } msix_clear_all_vectors(dev); qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE); qemu_get_buffer(f, dev->msix_pba, (n + 7) / 8); msix_update_function_masked(dev); for (vector = 0; vector < n; vector++) { msix_handle_mask_update(dev, vector, true); } }
/* Clean up resources for the device. */ void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar) { if (!msix_present(dev)) { return; } pci_del_capability(dev, PCI_CAP_ID_MSIX, MSIX_CAP_LENGTH); dev->msix_cap = 0; msix_free_irq_entries(dev); dev->msix_entries_nr = 0; memory_region_del_subregion(pba_bar, &dev->msix_pba_mmio); g_free(dev->msix_pba); dev->msix_pba = NULL; memory_region_del_subregion(table_bar, &dev->msix_table_mmio); g_free(dev->msix_table); dev->msix_table = NULL; g_free(dev->msix_entry_used); dev->msix_entry_used = NULL; dev->cap_present &= ~QEMU_PCI_CAP_MSIX; }
void msix_uninit_exclusive_bar(PCIDevice *dev) { if (msix_present(dev)) { msix_uninit(dev, &dev->msix_exclusive_bar, &dev->msix_exclusive_bar); } }