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: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20170711035620.4232-2-aik@ozlabs.ru>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Alexey Kardashevskiy 2017-07-11 13:56:19 +10:00 committed by Paolo Bonzini
parent 98fab4c163
commit 3df9d74806
20 changed files with 170 additions and 109 deletions

12
exec.c
View file

@ -480,19 +480,19 @@ 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 ?
IOMMU_WO : IOMMU_RO);
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));
*plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
@ -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