aboutsummaryrefslogtreecommitdiff
path: root/hw/pci-host
diff options
context:
space:
mode:
authorMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2018-01-08 18:16:34 +0000
committerMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2018-01-09 21:48:20 +0000
commitaea5b071012d3507885724362913d0b71dd6c303 (patch)
treec8708892b379a10a6653a765019d585e74d1c740 /hw/pci-host
parentf5980f757c028ec68ff8442c418db8462415af2a (diff)
apb: QOMify IOMMU
This is in preparation to split the IOMMU device out of the APB. As part of this commit we also enforce separation of the IOMMU and APB devices by using a QOM object link to pass the IOMMU reference and accessing the IOMMU registers via a separate memory region mapped into the APB config space rather than directly. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Acked-by: Artyom Tarasenko <atar4qemu@gmail.com>
Diffstat (limited to 'hw/pci-host')
-rw-r--r--hw/pci-host/apb.c77
1 files changed, 57 insertions, 20 deletions
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 44b08c090e..060e6e6d1c 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -36,6 +36,7 @@
#include "hw/pci-host/apb.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
+#include "qapi/error.h"
#include "qemu/log.h"
/* debug APB */
@@ -250,8 +251,8 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
return ret;
}
-static void iommu_config_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static void iommu_mem_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
{
IOMMUState *is = opaque;
@@ -295,7 +296,7 @@ static void iommu_config_write(void *opaque, hwaddr addr,
}
}
-static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
+static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size)
{
IOMMUState *is = opaque;
uint64_t val;
@@ -344,7 +345,6 @@ static void apb_config_writel (void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
APBState *s = opaque;
- IOMMUState *is = &s->iommu;
APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
@@ -352,9 +352,6 @@ static void apb_config_writel (void *opaque, hwaddr addr,
case 0x30 ... 0x4f: /* DMA error registers */
/* XXX: not implemented yet */
break;
- case 0x200 ... 0x217: /* IOMMU */
- iommu_config_write(is, (addr & 0x1f), val, size);
- break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
unsigned int ino = (addr & 0x3f) >> 3;
@@ -426,7 +423,6 @@ static uint64_t apb_config_readl (void *opaque,
hwaddr addr, unsigned size)
{
APBState *s = opaque;
- IOMMUState *is = &s->iommu;
uint32_t val;
switch (addr & 0xffff) {
@@ -434,9 +430,6 @@ static uint64_t apb_config_readl (void *opaque,
val = 0;
/* XXX: not implemented yet */
break;
- case 0x200 ... 0x217: /* IOMMU */
- val = iommu_config_read(is, (addr & 0x1f), size);
- break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
val = s->pci_irq_map[(addr & 0x3f) >> 3];
@@ -643,7 +636,6 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp)
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
PCIDevice *pci_dev;
- IOMMUState *is;
/* apb_config */
sysbus_mmio_map(sbd, 0, s->special_base);
@@ -665,14 +657,9 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp)
pci_create_simple(phb->bus, 0, "pbm-pci");
/* APB IOMMU */
- is = &s->iommu;
- memset(is, 0, sizeof(IOMMUState));
-
- memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
- TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev),
- "iommu-apb", UINT64_MAX);
- address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
- pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
+ memory_region_add_subregion_overlap(&s->apb_config, 0x200,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(s->iommu), 0), 1);
+ pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, s->iommu);
/* APB secondary busses */
pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
@@ -708,6 +695,12 @@ static void pci_pbm_init(Object *obj)
s->irq_request = NO_IRQ_REQUEST;
s->pci_irq_in = 0ULL;
+ /* IOMMU */
+ object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU,
+ (Object **) &s->iommu,
+ qdev_prop_allow_set_link_before_realize,
+ 0, NULL);
+
/* apb_config */
memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
"apb-config", 0x10000);
@@ -814,6 +807,49 @@ static const TypeInfo pbm_pci_bridge_info = {
},
};
+static const MemoryRegionOps iommu_mem_ops = {
+ .read = iommu_mem_read,
+ .write = iommu_mem_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void iommu_reset(DeviceState *d)
+{
+ IOMMUState *s = SUN4U_IOMMU(d);
+
+ memset(s->regs, 0, IOMMU_NREGS * sizeof(uint64_t));
+}
+
+static void iommu_init(Object *obj)
+{
+ IOMMUState *s = SUN4U_IOMMU(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
+ TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s),
+ "iommu-apb", UINT64_MAX);
+ address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as");
+
+ memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu",
+ IOMMU_NREGS * sizeof(uint64_t));
+ sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void iommu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = iommu_reset;
+}
+
+static const TypeInfo pbm_iommu_info = {
+ .name = TYPE_SUN4U_IOMMU,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IOMMUState),
+ .instance_init = iommu_init,
+ .class_init = iommu_class_init,
+};
+
static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
@@ -832,6 +868,7 @@ static void pbm_register_types(void)
type_register_static(&pbm_host_info);
type_register_static(&pbm_pci_host_info);
type_register_static(&pbm_pci_bridge_info);
+ type_register_static(&pbm_iommu_info);
type_register_static(&pbm_iommu_memory_region_info);
}