mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
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:
parent
98fab4c163
commit
3df9d74806
20 changed files with 170 additions and 109 deletions
|
@ -35,6 +35,10 @@
|
|||
#define MEMORY_REGION(obj) \
|
||||
OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
|
||||
|
||||
#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
|
||||
#define IOMMU_MEMORY_REGION(obj) \
|
||||
OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
|
||||
|
||||
typedef struct MemoryRegionOps MemoryRegionOps;
|
||||
typedef struct MemoryRegionMmio MemoryRegionMmio;
|
||||
|
||||
|
@ -198,16 +202,16 @@ struct MemoryRegionIOMMUOps {
|
|||
* set flag to IOMMU_NONE to mean that we don't need any
|
||||
* read/write permission checks, like, when for region replay.
|
||||
*/
|
||||
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr,
|
||||
IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr,
|
||||
IOMMUAccessFlags flag);
|
||||
/* Returns minimum supported page size */
|
||||
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
|
||||
uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu);
|
||||
/* Called when IOMMU Notifier flag changed */
|
||||
void (*notify_flag_changed)(MemoryRegion *iommu,
|
||||
void (*notify_flag_changed)(IOMMUMemoryRegion *iommu,
|
||||
IOMMUNotifierFlag old_flags,
|
||||
IOMMUNotifierFlag new_flags);
|
||||
/* Set this up to provide customized IOMMU replay function */
|
||||
void (*replay)(MemoryRegion *iommu, IOMMUNotifier *notifier);
|
||||
void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
|
||||
};
|
||||
|
||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||
|
@ -227,9 +231,9 @@ struct MemoryRegion {
|
|||
bool flush_coalesced_mmio;
|
||||
bool global_locking;
|
||||
uint8_t dirty_log_mask;
|
||||
bool is_iommu;
|
||||
RAMBlock *ram_block;
|
||||
Object *owner;
|
||||
const MemoryRegionIOMMUOps *iommu_ops;
|
||||
|
||||
const MemoryRegionOps *ops;
|
||||
void *opaque;
|
||||
|
@ -252,6 +256,12 @@ struct MemoryRegion {
|
|||
const char *name;
|
||||
unsigned ioeventfd_nb;
|
||||
MemoryRegionIoeventfd *ioeventfds;
|
||||
};
|
||||
|
||||
struct IOMMUMemoryRegion {
|
||||
MemoryRegion parent_obj;
|
||||
|
||||
const MemoryRegionIOMMUOps *iommu_ops;
|
||||
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
|
||||
IOMMUNotifierFlag iommu_notify_flags;
|
||||
};
|
||||
|
@ -618,13 +628,13 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
|
|||
* An IOMMU region translates addresses and forwards accesses to a target
|
||||
* memory region.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized
|
||||
* @iommu_mr: the #IOMMUMemoryRegion to be initialized
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: a function that translates addresses into the @target region
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @size: size of the region.
|
||||
*/
|
||||
void memory_region_init_iommu(MemoryRegion *mr,
|
||||
void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
|
||||
struct Object *owner,
|
||||
const MemoryRegionIOMMUOps *ops,
|
||||
const char *name,
|
||||
|
@ -679,20 +689,25 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
|
|||
}
|
||||
|
||||
/**
|
||||
* memory_region_is_iommu: check whether a memory region is an iommu
|
||||
* memory_region_get_iommu: check whether a memory region is an iommu
|
||||
*
|
||||
* Returns %true is a memory region is an iommu.
|
||||
* Returns pointer to IOMMUMemoryRegion if a memory region is an iommu,
|
||||
* otherwise NULL.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
static inline bool memory_region_is_iommu(MemoryRegion *mr)
|
||||
static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_is_iommu(mr->alias);
|
||||
return memory_region_get_iommu(mr->alias);
|
||||
}
|
||||
return mr->iommu_ops;
|
||||
if (mr->is_iommu) {
|
||||
return (IOMMUMemoryRegion *) mr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
|
||||
|
||||
/**
|
||||
* memory_region_iommu_get_min_page_size: get minimum supported page size
|
||||
|
@ -700,9 +715,9 @@ static inline bool memory_region_is_iommu(MemoryRegion *mr)
|
|||
*
|
||||
* Returns minimum supported page size for an iommu.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
* @iommu_mr: the memory region being queried
|
||||
*/
|
||||
uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
|
||||
uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr);
|
||||
|
||||
/**
|
||||
* memory_region_notify_iommu: notify a change in an IOMMU translation entry.
|
||||
|
@ -716,12 +731,12 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
|
|||
* Note: for any IOMMU implementation, an in-place mapping change
|
||||
* should be notified with an UNMAP followed by a MAP.
|
||||
*
|
||||
* @mr: the memory region that was changed
|
||||
* @iommu_mr: the memory region that was changed
|
||||
* @entry: the new entry in the IOMMU translation table. The entry
|
||||
* replaces all old entries for the same virtual I/O address range.
|
||||
* Deleted entries have .@perm == 0.
|
||||
*/
|
||||
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||
void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
|
||||
IOMMUTLBEntry entry);
|
||||
|
||||
/**
|
||||
|
@ -756,18 +771,18 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
|
|||
* a notifier with the minimum page granularity returned by
|
||||
* mr->iommu_ops->get_page_size().
|
||||
*
|
||||
* @mr: the memory region to observe
|
||||
* @iommu_mr: the memory region to observe
|
||||
* @n: the notifier to which to replay iommu mappings
|
||||
*/
|
||||
void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n);
|
||||
void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
|
||||
|
||||
/**
|
||||
* memory_region_iommu_replay_all: replay existing IOMMU translations
|
||||
* to all the notifiers registered.
|
||||
*
|
||||
* @mr: the memory region to observe
|
||||
* @iommu_mr: the memory region to observe
|
||||
*/
|
||||
void memory_region_iommu_replay_all(MemoryRegion *mr);
|
||||
void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr);
|
||||
|
||||
/**
|
||||
* memory_region_unregister_iommu_notifier: unregister a notifier for
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue