memory/iommu: introduce IOMMUMemoryRegionClass

This finishes QOM'fication of IOMMUMemoryRegion by introducing
a IOMMUMemoryRegionClass. This also provides a fastpath analog for
IOMMU_MEMORY_REGION_GET_CLASS().

This makes IOMMUMemoryRegion an abstract class.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170711035620.4232-3-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:20 +10:00 committed by Paolo Bonzini
parent 3df9d74806
commit 1221a47467
15 changed files with 205 additions and 70 deletions

View file

@ -1506,19 +1506,20 @@ void memory_region_init_rom_device(MemoryRegion *mr,
mr->ram_block = qemu_ram_alloc(size, mr, errp);
}
void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
void memory_region_init_iommu(void *_iommu_mr,
size_t instance_size,
const char *mrtypename,
Object *owner,
const MemoryRegionIOMMUOps *ops,
const char *name,
uint64_t size)
{
struct IOMMUMemoryRegion *iommu_mr;
struct MemoryRegion *mr;
object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
mr = MEMORY_REGION(iommu_mr);
object_initialize(_iommu_mr, instance_size, mrtypename);
mr = MEMORY_REGION(_iommu_mr);
memory_region_do_init(mr, owner, name, size);
iommu_mr = IOMMU_MEMORY_REGION(mr);
iommu_mr->iommu_ops = ops,
mr->terminates = true; /* then re-forwards */
QLIST_INIT(&iommu_mr->iommu_notify);
iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
@ -1620,16 +1621,16 @@ static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
{
IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
IOMMUNotifier *iommu_notifier;
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
flags |= iommu_notifier->notifier_flags;
}
if (flags != iommu_mr->iommu_notify_flags &&
iommu_mr->iommu_ops->notify_flag_changed) {
iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
iommu_mr->iommu_notify_flags,
flags);
if (flags != iommu_mr->iommu_notify_flags && imrc->notify_flag_changed) {
imrc->notify_flag_changed(iommu_mr,
iommu_mr->iommu_notify_flags,
flags);
}
iommu_mr->iommu_notify_flags = flags;
@ -1655,8 +1656,10 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
{
if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
if (imrc->get_min_page_size) {
return imrc->get_min_page_size(iommu_mr);
}
return TARGET_PAGE_SIZE;
}
@ -1664,19 +1667,20 @@ uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
MemoryRegion *mr = MEMORY_REGION(iommu_mr);
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
hwaddr addr, granularity;
IOMMUTLBEntry iotlb;
/* If the IOMMU has its own replay callback, override */
if (iommu_mr->iommu_ops->replay) {
iommu_mr->iommu_ops->replay(iommu_mr, n);
if (imrc->replay) {
imrc->replay(iommu_mr, n);
return;
}
granularity = memory_region_iommu_get_min_page_size(iommu_mr);
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE);
if (iotlb.perm != IOMMU_NONE) {
n->notify(n, &iotlb);
}
@ -2855,8 +2859,10 @@ static const TypeInfo memory_region_info = {
static const TypeInfo iommu_memory_region_info = {
.parent = TYPE_MEMORY_REGION,
.name = TYPE_IOMMU_MEMORY_REGION,
.class_size = sizeof(IOMMUMemoryRegionClass),
.instance_size = sizeof(IOMMUMemoryRegion),
.instance_init = iommu_memory_region_initfn,
.abstract = true,
};
static void memory_register_types(void)