aboutsummaryrefslogtreecommitdiff
path: root/hw/pci-host/apb.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/pci-host/apb.c')
-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);
}