*/
MemoryRegion bar;
MemoryRegion ivshmem;
+ MemoryRegion msix_bar;
uint64_t ivshmem_size; /* size of shared memory region */
int shm_fd; /* shared memory file descriptor */
/* allocate the MSI-X vectors */
- if (!msix_init(&s->dev, s->vectors, 1, 0)) {
- pci_register_bar(&s->dev, 1,
- msix_bar_size(&s->dev),
- PCI_BASE_ADDRESS_SPACE_MEMORY,
- msix_mmio_map);
+ memory_region_init(&s->msix_bar, "ivshmem-msix", 4096);
+ if (!msix_init(&s->dev, s->vectors, &s->msix_bar, 1, 0)) {
+ pci_register_bar_region(&s->dev, 1,
+ PCI_BASE_ADDRESS_SPACE_MEMORY,
+ &s->msix_bar);
IVSHMEM_DPRINTF("msix initialized (%d vectors)\n", s->vectors);
} else {
IVSHMEM_DPRINTF("msix initialization failed\n");
return 0;
}
-static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t msix_mmio_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
PCIDevice *dev = opaque;
unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
return pci_get_long(page + offset);
}
-static uint32_t msix_mmio_read_unallowed(void *opaque, target_phys_addr_t addr)
-{
- fprintf(stderr, "MSI-X: only dword read is allowed!\n");
- return 0;
-}
-
static uint8_t msix_pending_mask(int vector)
{
return 1 << (vector % 8);
}
}
-static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
+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;
msix_handle_mask_update(dev, vector);
}
-static void msix_mmio_write_unallowed(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- fprintf(stderr, "MSI-X: only dword write is allowed!\n");
-}
-
-static CPUWriteMemoryFunc * const msix_mmio_write[] = {
- msix_mmio_write_unallowed, msix_mmio_write_unallowed, msix_mmio_writel
-};
-
-static CPUReadMemoryFunc * const msix_mmio_read[] = {
- msix_mmio_read_unallowed, msix_mmio_read_unallowed, msix_mmio_readl
+static const MemoryRegionOps msix_mmio_ops = {
+ .read = msix_mmio_read,
+ .write = msix_mmio_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
-/* Should be called from device's map method. */
-void msix_mmio_map(PCIDevice *d, int region_num,
- pcibus_t addr, pcibus_t size, int type)
+static void msix_mmio_setup(PCIDevice *d, MemoryRegion *bar)
{
uint8_t *config = d->config + d->msix_cap;
uint32_t table = pci_get_long(config + PCI_MSIX_TABLE);
uint32_t offset = table & ~(MSIX_PAGE_SIZE - 1);
/* TODO: for assigned devices, we'll want to make it possible to map
* pending bits separately in case they are in a separate bar. */
- int table_bir = table & PCI_MSIX_FLAGS_BIRMASK;
- if (table_bir != region_num)
- return;
- if (size <= offset)
- return;
- cpu_register_physical_memory(addr + offset, size - offset,
- d->msix_mmio_index);
+ memory_region_add_subregion(bar, offset, &d->msix_mmio);
}
static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
/* Initialize the MSI-X structures. Note: if MSI-X is supported, BAR size is
* modified, it should be retrieved with msix_bar_size. */
int msix_init(struct PCIDevice *dev, unsigned short nentries,
+ MemoryRegion *bar,
unsigned bar_nr, unsigned bar_size)
{
int ret;
dev->msix_table_page = qemu_mallocz(MSIX_PAGE_SIZE);
msix_mask_all(dev, nentries);
- dev->msix_mmio_index = cpu_register_io_memory(msix_mmio_read,
- msix_mmio_write, dev,
- DEVICE_NATIVE_ENDIAN);
- if (dev->msix_mmio_index == -1) {
- ret = -EBUSY;
- goto err_index;
- }
+ memory_region_init_io(&dev->msix_mmio, &msix_mmio_ops, dev,
+ "msix", MSIX_PAGE_SIZE);
dev->msix_entries_nr = nentries;
ret = msix_add_config(dev, nentries, bar_nr, bar_size);
goto err_config;
dev->cap_present |= QEMU_PCI_CAP_MSIX;
+ msix_mmio_setup(dev, bar);
return 0;
err_config:
dev->msix_entries_nr = 0;
- cpu_unregister_io_memory(dev->msix_mmio_index);
-err_index:
+ memory_region_destroy(&dev->msix_mmio);
qemu_free(dev->msix_table_page);
dev->msix_table_page = NULL;
qemu_free(dev->msix_entry_used);
}
/* Clean up resources for the device. */
-int msix_uninit(PCIDevice *dev)
+int msix_uninit(PCIDevice *dev, MemoryRegion *bar)
{
if (!(dev->cap_present & QEMU_PCI_CAP_MSIX))
return 0;
dev->msix_cap = 0;
msix_free_irq_entries(dev);
dev->msix_entries_nr = 0;
- cpu_unregister_io_memory(dev->msix_mmio_index);
+ memory_region_del_subregion(bar, &dev->msix_mmio);
+ memory_region_destroy(&dev->msix_mmio);
qemu_free(dev->msix_table_page);
dev->msix_table_page = NULL;
qemu_free(dev->msix_entry_used);
pci_set_word(config + 0x2e, vdev->device_id);
config[0x3d] = 1;
- if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
- pci_register_bar(&proxy->pci_dev, 1,
- msix_bar_size(&proxy->pci_dev),
- PCI_BASE_ADDRESS_SPACE_MEMORY,
- msix_mmio_map);
+ memory_region_init(&proxy->msix_bar, "virtio-msix", 4096);
+ if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors,
+ &proxy->msix_bar, 1, 0)) {
+ pci_register_bar_region(&proxy->pci_dev, 1,
+ PCI_BASE_ADDRESS_SPACE_MEMORY,
+ &proxy->msix_bar);
} else
vdev->nvectors = 0;
static int virtio_exit_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ int r;
memory_region_destroy(&proxy->bar);
- return msix_uninit(pci_dev);
+ r = msix_uninit(pci_dev, &proxy->msix_bar);
+ memory_region_destroy(&proxy->msix_bar);
+ return r;
}
static int virtio_blk_exit_pci(PCIDevice *pci_dev)