Commit 3df9d748 authored by Alexey Kardashevskiy's avatar Alexey Kardashevskiy Committed by Paolo Bonzini
Browse files

memory/iommu: QOM'fy IOMMU MemoryRegion



This defines new QOM object - IOMMUMemoryRegion - with MemoryRegion
as a parent.

This moves IOMMU-related fields from MR to IOMMU MR. However to avoid
dymanic QOM casting in fast path (address_space_translate, etc),
this adds an @is_iommu boolean flag to MR and provides new helper to
do simple cast to IOMMU MR - memory_region_get_iommu. The flag
is set in the instance init callback. This defines
memory_region_is_iommu as memory_region_get_iommu()!=NULL.

This switches MemoryRegion to IOMMUMemoryRegion in most places except
the ones where MemoryRegion may be an alias.

Signed-off-by: default avatarAlexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Message-Id: <20170711035620.4232-2-aik@ozlabs.ru>
Acked-by: default avatarCornelia Huck <cohuck@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 98fab4c1
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -480,18 +480,18 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
{
    IOMMUTLBEntry iotlb;
    MemoryRegionSection *section;
    MemoryRegion *mr;
    IOMMUMemoryRegion *iommu_mr;

    for (;;) {
        AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
        section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
        mr = section->mr;

        if (!mr->iommu_ops) {
        iommu_mr = memory_region_get_iommu(section->mr);
        if (!iommu_mr) {
            break;
        }

        iotlb = mr->iommu_ops->translate(mr, addr, is_write ?
        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
                                               IOMMU_WO : IOMMU_RO);
        addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
                | (addr & iotlb.addr_mask));
@@ -588,7 +588,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,

    section = address_space_translate_internal(d, addr, xlat, plen, false);

    assert(!section->mr->iommu_ops);
    assert(!memory_region_is_iommu(section->mr));
    return section;
}
#endif
+5 −3
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ typedef struct TyphoonPchip {
    MemoryRegion reg_conf;

    AddressSpace iommu_as;
    MemoryRegion iommu;
    IOMMUMemoryRegion iommu;

    uint64_t ctl;
    TyphoonWindow win[4];
@@ -663,7 +663,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
/* Handle PCI-to-system address translation.  */
/* TODO: A translation failure here ought to set PCI error codes on the
   Pchip and generate a machine check interrupt.  */
static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
                                             hwaddr addr,
                                             IOMMUAccessFlags flag)
{
    TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
@@ -893,7 +894,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
    /* Host memory as seen from the PCI side, via the IOMMU.  */
    memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
                             "iommu-typhoon", UINT64_MAX);
    address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
    address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
                       "pchip0-pci");
    pci_setup_iommu(b, typhoon_pci_dma_iommu, s);

    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
+4 −4
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ typedef struct rc4030State
    qemu_irq jazz_bus_irq;

    /* whole DMA memory region, root of DMA address space */
    MemoryRegion dma_mr;
    IOMMUMemoryRegion dma_mr;
    AddressSpace dma_as;

    MemoryRegion iomem_chipset;
@@ -488,7 +488,7 @@ static const MemoryRegionOps jazzio_ops = {
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                          IOMMUAccessFlags flag)
{
    rc4030State *s = container_of(iommu, rc4030State, dma_mr);
@@ -679,7 +679,7 @@ static void rc4030_realize(DeviceState *dev, Error **errp)

    memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
                             "rc4030.dma", UINT32_MAX);
    address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
    address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
}

static void rc4030_unrealize(DeviceState *dev, Error **errp)
@@ -717,7 +717,7 @@ static void rc4030_register_types(void)

type_init(rc4030_register_types)

DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr)
DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
{
    DeviceState *dev;

+5 −4
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ struct AMDVIAddressSpace {
    uint8_t bus_num;            /* bus number                           */
    uint8_t devfn;              /* device function                      */
    AMDVIState *iommu_state;    /* AMDVI - one per machine              */
    MemoryRegion iommu;         /* Device's address translation region  */
    IOMMUMemoryRegion iommu;    /* Device's address translation region  */
    MemoryRegion iommu_ir;      /* Device's interrupt remapping region  */
    AddressSpace as;            /* device's corresponding address space */
};
@@ -987,7 +987,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
    return addr >= AMDVI_INT_ADDR_FIRST && addr <= AMDVI_INT_ADDR_LAST;
}

static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                     IOMMUAccessFlags flag)
{
    AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
@@ -1046,7 +1046,8 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)

        memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
                                 &s->iommu_ops, "amd-iommu", UINT64_MAX);
        address_space_init(&iommu_as[devfn]->as, &iommu_as[devfn]->iommu,
        address_space_init(&iommu_as[devfn]->as,
                           MEMORY_REGION(&iommu_as[devfn]->iommu),
                           "amd-iommu");
    }
    return &iommu_as[devfn]->as;
@@ -1067,7 +1068,7 @@ static const MemoryRegionOps mmio_mem_ops = {
    }
};

static void amdvi_iommu_notify_flag_changed(MemoryRegion *iommu,
static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
                                            IOMMUNotifierFlag old,
                                            IOMMUNotifierFlag new)
{
+9 −8
Original line number Diff line number Diff line
@@ -972,9 +972,9 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
    /* Turn off first then on the other */
    if (use_iommu) {
        memory_region_set_enabled(&as->sys_alias, false);
        memory_region_set_enabled(&as->iommu, true);
        memory_region_set_enabled(MEMORY_REGION(&as->iommu), true);
    } else {
        memory_region_set_enabled(&as->iommu, false);
        memory_region_set_enabled(MEMORY_REGION(&as->iommu), false);
        memory_region_set_enabled(&as->sys_alias, true);
    }

@@ -1366,7 +1366,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
                                           void *private)
{
    memory_region_notify_iommu((MemoryRegion *)private, *entry);
    memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
    return 0;
}

@@ -2264,7 +2264,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
    }
}

static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                         IOMMUAccessFlags flag)
{
    VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
@@ -2303,7 +2303,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
    return iotlb;
}

static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
                                          IOMMUNotifierFlag old,
                                          IOMMUNotifierFlag new)
{
@@ -2736,7 +2736,8 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
        memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
                                            &vtd_dev_as->sys_alias, 1);
        memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
                                            &vtd_dev_as->iommu, 1);
                                            MEMORY_REGION(&vtd_dev_as->iommu),
                                            1);
        vtd_switch_address_space(vtd_dev_as);
    }
    return vtd_dev_as;
@@ -2816,9 +2817,9 @@ static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
    return 0;
}

static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
static void vtd_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
    VTDAddressSpace *vtd_as = container_of(mr, VTDAddressSpace, iommu);
    VTDAddressSpace *vtd_as = container_of(iommu_mr, VTDAddressSpace, iommu);
    IntelIOMMUState *s = vtd_as->iommu_state;
    uint8_t bus_n = pci_bus_num(vtd_as->bus);
    VTDContextEntry ce;
Loading