Signed-off-by: Avi Kivity <avi@xxxxxxxxxx> --- hw/device-assignment.c | 158 ++++++++++++++++++++++-------------------------- hw/device-assignment.h | 6 +- 2 files changed, 75 insertions(+), 89 deletions(-) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index 59d9b92..942d3af 100644 --- a/hw/device-assignment.c +++ b/hw/device-assignment.c @@ -42,6 +42,8 @@ #include <pci/header.h> #include "sysemu.h" +#define MSIX_PAGE_SIZE 0x1000 + /* From linux/ioport.h */ #define IORESOURCE_IO 0x00000100 /* Resource type */ #define IORESOURCE_MEM 0x00000200 @@ -97,7 +99,7 @@ static uint32_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, uint32_t addr, int len, uint32_t *val) { uint32_t ret = 0; - uint32_t offset = addr - dev_region->e_physbase; + uint32_t offset = addr; int fd = dev_region->region->resource_fd; if (fd >= 0) { @@ -252,33 +254,25 @@ static void slow_bar_writel(void *opaque, target_phys_addr_t addr, uint32_t val) *out = val; } -static CPUWriteMemoryFunc * const slow_bar_write[] = { - &slow_bar_writeb, - &slow_bar_writew, - &slow_bar_writel -}; - -static CPUReadMemoryFunc * const slow_bar_read[] = { - &slow_bar_readb, - &slow_bar_readw, - &slow_bar_readl +static const MemoryRegionOps slow_bar_ops = { + .old_mmio = { + .read = { slow_bar_readb, slow_bar_readw, slow_bar_readl, }, + .write = { slow_bar_writeb, slow_bar_writew, slow_bar_writel, }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num, - pcibus_t e_phys, pcibus_t e_size, int type) +static void assigned_dev_iomem_setup(PCIDevice *pci_dev, int region_num, + pcibus_t e_size) { AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); AssignedDevRegion *region = &r_dev->v_addrs[region_num]; PCIRegion *real_region = &r_dev->real_device.regions[region_num]; - DEBUG("e_phys=%08" FMT_PCIBUS " r_virt=%p type=%d len=%08" FMT_PCIBUS " region_num=%d \n", - e_phys, region->u.r_virtbase, type, e_size, region_num); - - region->e_physbase = e_phys; - region->e_size = e_size; - if (e_size > 0) { - cpu_register_physical_memory(e_phys, e_size, region->memory_index); + memory_region_init(®ion->container, "assigned-dev-container", + e_size); + memory_region_add_subregion(®ion->container, 0, ®ion->real_iomem); /* deal with MSI-X MMIO page */ if (real_region->base_addr <= r_dev->msix_table_addr && @@ -286,27 +280,39 @@ static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num, r_dev->msix_table_addr) { int offset = r_dev->msix_table_addr - real_region->base_addr; - cpu_register_physical_memory(e_phys + offset, - TARGET_PAGE_SIZE, r_dev->mmio_index); + memory_region_add_subregion_overlap(®ion->container, + offset, + &r_dev->mmio, + 1); } } } -static void assigned_dev_ioport_map(PCIDevice *pci_dev, int region_num, - pcibus_t addr, pcibus_t size, int type) +static const MemoryRegionPortio assigned_dev_old_portio[] = { + { 0x10000, 1, .read = assigned_dev_ioport_readb, }, + { 0x10000, 2, .read = assigned_dev_ioport_readw, }, + { 0x10000, 4, .read = assigned_dev_ioport_readl, }, + { 0x10000, 1, .write = assigned_dev_ioport_writeb, }, + { 0x10000, 2, .write = assigned_dev_ioport_writew, }, + { 0x10000, 4, .write = assigned_dev_ioport_writel, }, + PORTIO_END_OF_LIST() +}; + +static const MemoryRegionOps assigned_dev_ioport_ops = { + .old_portio = assigned_dev_old_portio, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void assigned_dev_ioport_setup(PCIDevice *pci_dev, int region_num, + pcibus_t size) { AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); AssignedDevRegion *region = &r_dev->v_addrs[region_num]; - int first_map = (region->e_size == 0); int r; - region->e_physbase = addr; region->e_size = size; - DEBUG("e_phys=0x%" FMT_PCIBUS " r_baseport=%x type=0x%x len=%" FMT_PCIBUS " region_num=%d \n", - addr, region->u.r_baseport, type, size, region_num); - - if (first_map && region->region->resource_fd < 0) { + if (region->region->resource_fd < 0) { r = kvm_add_ioport_region(region->u.r_baseport, region->r_size, pci_dev->qdev.hotplugged); if (r < 0) { @@ -314,19 +320,11 @@ static void assigned_dev_ioport_map(PCIDevice *pci_dev, int region_num, __func__); } } - - register_ioport_read(addr, size, 1, assigned_dev_ioport_readb, - (r_dev->v_addrs + region_num)); - register_ioport_read(addr, size, 2, assigned_dev_ioport_readw, - (r_dev->v_addrs + region_num)); - register_ioport_read(addr, size, 4, assigned_dev_ioport_readl, - (r_dev->v_addrs + region_num)); - register_ioport_write(addr, size, 1, assigned_dev_ioport_writeb, - (r_dev->v_addrs + region_num)); - register_ioport_write(addr, size, 2, assigned_dev_ioport_writew, - (r_dev->v_addrs + region_num)); - register_ioport_write(addr, size, 4, assigned_dev_ioport_writel, - (r_dev->v_addrs + region_num)); + memory_region_init(®ion->container, "assigned-dev-container", size); + memory_region_init_io(®ion->real_iomem, &assigned_dev_ioport_ops, + r_dev->v_addrs + region_num, + "assigned-dev-iomem", size); + memory_region_add_subregion(®ion->container, 0, ®ion->real_iomem); } static uint32_t assigned_dev_pci_read(PCIDevice *d, int pos, int len) @@ -562,7 +560,6 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, : PCI_BASE_ADDRESS_SPACE_MEMORY; /* map physical memory */ - pci_dev->v_addrs[i].e_physbase = cur_region->base_addr; pci_dev->v_addrs[i].u.r_virtbase = mmap(NULL, cur_region->size, PROT_WRITE | PROT_READ, MAP_SHARED, @@ -591,24 +588,24 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, "due to that.\n", i, (unsigned long long)cur_region->base_addr, cur_region->size); - pci_dev->v_addrs[i].memory_index = - cpu_register_io_memory(slow_bar_read, slow_bar_write, - &pci_dev->v_addrs[i], - DEVICE_NATIVE_ENDIAN); + memory_region_init_io(&pci_dev->v_addrs[i].real_iomem, + &slow_bar_ops, &pci_dev->v_addrs[i], + "assigned-dev-slow-bar", + cur_region->size); } else { void *virtbase = pci_dev->v_addrs[i].u.r_virtbase; char name[32]; snprintf(name, sizeof(name), "%s.bar%d", pci_dev->dev.qdev.info->name, i); - pci_dev->v_addrs[i].memory_index = - qemu_ram_alloc_from_ptr( - &pci_dev->dev.qdev, - name, cur_region->size, - virtbase); + memory_region_init_ram_ptr(&pci_dev->v_addrs[i].real_iomem, + &pci_dev->dev.qdev, + name, cur_region->size, + virtbase); } - pci_register_bar((PCIDevice *) pci_dev, i, cur_region->size, t, - assigned_dev_iomem_map); + assigned_dev_iomem_setup(&pci_dev->dev, i, cur_region->size); + pci_register_bar_region((PCIDevice *) pci_dev, i, t, + &pci_dev->v_addrs[i].container); continue; } else { /* handle port io regions */ @@ -629,17 +626,14 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, pci_dev->v_addrs[i].region->resource_fd = -1; } - pci_dev->v_addrs[i].e_physbase = cur_region->base_addr; pci_dev->v_addrs[i].u.r_baseport = cur_region->base_addr; pci_dev->v_addrs[i].r_size = cur_region->size; pci_dev->v_addrs[i].e_size = 0; - pci_register_bar((PCIDevice *) pci_dev, i, - cur_region->size, PCI_BASE_ADDRESS_SPACE_IO, - assigned_dev_ioport_map); - - /* not relevant for port io */ - pci_dev->v_addrs[i].memory_index = 0; + assigned_dev_ioport_setup(&pci_dev->dev, i, cur_region->size); + pci_register_bar_region((PCIDevice *) pci_dev, i, + PCI_BASE_ADDRESS_SPACE_IO, + &pci_dev->v_addrs[i].container); } } @@ -816,6 +810,9 @@ static void free_assigned_device(AssignedDevice *dev) { int i; + if (dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { + assigned_dev_unregister_msix_mmio(dev); + } for (i = 0; i < dev->real_device.region_number; i++) { PCIRegion *pci_region = &dev->real_device.regions[i]; AssignedDevRegion *region = &dev->v_addrs[i]; @@ -830,16 +827,10 @@ static void free_assigned_device(AssignedDevice *dev) } } else if (pci_region->type & IORESOURCE_MEM) { if (region->u.r_virtbase) { - if (region->e_size > 0) { - cpu_register_physical_memory(region->e_physbase, - region->e_size, - IO_MEM_UNASSIGNED); - } - if (region->r_size & 0xFFF) { - cpu_unregister_io_memory(region->memory_index); - } else { - qemu_ram_free_from_ptr(region->memory_index); - } + memory_region_del_subregion(®ion->container, + ®ion->real_iomem); + memory_region_destroy(®ion->real_iomem); + memory_region_destroy(®ion->container); if (munmap(region->u.r_virtbase, (pci_region->size + 0xFFF) & 0xFFFFF000)) { fprintf(stderr, @@ -853,9 +844,6 @@ static void free_assigned_device(AssignedDevice *dev) } } - if (dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { - assigned_dev_unregister_msix_mmio(dev); - } if (dev->real_device.config_fd >= 0) { close(dev->real_device.config_fd); } @@ -1624,12 +1612,12 @@ static void msix_mmio_writeb(void *opaque, (val & 0xff) << (8*(addr & 3))); } -static CPUWriteMemoryFunc *msix_mmio_write[] = { - msix_mmio_writeb, msix_mmio_writew, msix_mmio_writel -}; - -static CPUReadMemoryFunc *msix_mmio_read[] = { - msix_mmio_readb, msix_mmio_readw, msix_mmio_readl +static const MemoryRegionOps msix_mmio_ops = { + .old_mmio = { + .read = { msix_mmio_readb, msix_mmio_readw, msix_mmio_readl, }, + .write = { msix_mmio_writeb, msix_mmio_writew, msix_mmio_writel, }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; static int assigned_dev_register_msix_mmio(AssignedDevice *dev) @@ -1643,9 +1631,8 @@ static int assigned_dev_register_msix_mmio(AssignedDevice *dev) return -EFAULT; } memset(dev->msix_table_page, 0, 0x1000); - dev->mmio_index = cpu_register_io_memory( - msix_mmio_read, msix_mmio_write, dev, - DEVICE_NATIVE_ENDIAN); + memory_region_init_io(&dev->mmio, &msix_mmio_ops, dev, + "assigned-dev-msix", MSIX_PAGE_SIZE); return 0; } @@ -1654,8 +1641,7 @@ static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev) if (!dev->msix_table_page) return; - cpu_unregister_io_memory(dev->mmio_index); - dev->mmio_index = 0; + memory_region_destroy(&dev->mmio); if (munmap(dev->msix_table_page, 0x1000) == -1) { fprintf(stderr, "error unmapping msix_table_page! %s\n", diff --git a/hw/device-assignment.h b/hw/device-assignment.h index ae1bc58..3a3d99d 100644 --- a/hw/device-assignment.h +++ b/hw/device-assignment.h @@ -62,8 +62,8 @@ typedef struct { } PCIDevRegions; typedef struct { - pcibus_t e_physbase; - ram_addr_t memory_index; + MemoryRegion container; + MemoryRegion real_iomem; union { void *r_virtbase; /* mmapped access address for memory regions */ uint32_t r_baseport; /* the base guest port for I/O regions */ @@ -108,7 +108,7 @@ typedef struct AssignedDevice { struct kvm_irq_routing_entry *entry; void *msix_table_page; target_phys_addr_t msix_table_addr; - int mmio_index; + MemoryRegion mmio; uint32_t emulate_cmd_mask; char *configfd_name; int32_t bootindex; -- 1.7.5.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html