/* 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)); } }
static void msix_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) { PCIDevice *dev = opaque; unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3; int vector = offset / PCI_MSIX_ENTRY_SIZE; pci_set_long(dev->msix_table_page + offset, val); msix_handle_mask_update(dev, vector); }
static void msix_table_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIDevice *dev = opaque; int vector = addr / PCI_MSIX_ENTRY_SIZE; bool was_masked; was_masked = msix_is_masked(dev, vector); pci_set_long(dev->msix_table + addr, val); msix_handle_mask_update(dev, vector, was_masked); }
static void msix_mask_all(struct PCIDevice *dev, unsigned nentries) { int vector; for (vector = 0; vector < nentries; ++vector) { unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; bool was_masked = msix_is_masked(dev, vector); dev->msix_table[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT; msix_handle_mask_update(dev, vector, was_masked); } }
/* 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); } }
static void msix_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) { PCIDevice *dev = opaque; unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3; int vector = offset / PCI_MSIX_ENTRY_SIZE; int was_masked = msix_is_masked(dev, vector); pci_set_long(dev->msix_table_page + offset, val); if (kvm_enabled() && kvm_irqchip_in_kernel()) { kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector)); } if (was_masked != msix_is_masked(dev, vector) && dev->msix_mask_notifier) { int r = dev->msix_mask_notifier(dev, vector, msix_is_masked(dev, vector)); assert(r >= 0); } msix_handle_mask_update(dev, vector); }