Signed-off-by: Avi Kivity <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html