memory: introduce IOMMUOps.notify_flag_changed
The new interface can be used to replace the old notify_started() and notify_stopped(). Meanwhile it provides explicit flags so that IOMMUs can know what kind of notifications it is requested for. Acked-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <1474606948-14391-3-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
cdb3081269
commit
5bf3d31903
@ -1066,7 +1066,9 @@ static const MemoryRegionOps mmio_mem_ops = {
|
||||
}
|
||||
};
|
||||
|
||||
static void amdvi_iommu_notify_started(MemoryRegion *iommu)
|
||||
static void amdvi_iommu_notify_flag_changed(MemoryRegion *iommu,
|
||||
IOMMUNotifierFlag old,
|
||||
IOMMUNotifierFlag new)
|
||||
{
|
||||
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
|
||||
|
||||
@ -1080,7 +1082,7 @@ static void amdvi_init(AMDVIState *s)
|
||||
amdvi_iotlb_reset(s);
|
||||
|
||||
s->iommu_ops.translate = amdvi_translate;
|
||||
s->iommu_ops.notify_started = amdvi_iommu_notify_started;
|
||||
s->iommu_ops.notify_flag_changed = amdvi_iommu_notify_flag_changed;
|
||||
s->devtab_len = 0;
|
||||
s->cmdbuf_len = 0;
|
||||
s->cmdbuf_head = 0;
|
||||
|
@ -1974,7 +1974,9 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vtd_iommu_notify_started(MemoryRegion *iommu)
|
||||
static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
|
||||
IOMMUNotifierFlag old,
|
||||
IOMMUNotifierFlag new)
|
||||
{
|
||||
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
|
||||
|
||||
@ -2348,7 +2350,7 @@ static void vtd_init(IntelIOMMUState *s)
|
||||
memset(s->womask, 0, DMAR_REG_SIZE);
|
||||
|
||||
s->iommu_ops.translate = vtd_iommu_translate;
|
||||
s->iommu_ops.notify_started = vtd_iommu_notify_started;
|
||||
s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed;
|
||||
s->root = 0;
|
||||
s->root_extended = false;
|
||||
s->dmar_enabled = false;
|
||||
|
@ -156,14 +156,17 @@ static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu)
|
||||
return 1ULL << tcet->page_shift;
|
||||
}
|
||||
|
||||
static void spapr_tce_notify_started(MemoryRegion *iommu)
|
||||
static void spapr_tce_notify_flag_changed(MemoryRegion *iommu,
|
||||
IOMMUNotifierFlag old,
|
||||
IOMMUNotifierFlag new)
|
||||
{
|
||||
spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), true);
|
||||
}
|
||||
struct sPAPRTCETable *tbl = container_of(iommu, sPAPRTCETable, iommu);
|
||||
|
||||
static void spapr_tce_notify_stopped(MemoryRegion *iommu)
|
||||
{
|
||||
spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), false);
|
||||
if (old == IOMMU_NOTIFIER_NONE && new != IOMMU_NOTIFIER_NONE) {
|
||||
spapr_tce_set_need_vfio(tbl, true);
|
||||
} else if (old != IOMMU_NOTIFIER_NONE && new == IOMMU_NOTIFIER_NONE) {
|
||||
spapr_tce_set_need_vfio(tbl, false);
|
||||
}
|
||||
}
|
||||
|
||||
static int spapr_tce_table_post_load(void *opaque, int version_id)
|
||||
@ -246,8 +249,7 @@ static const VMStateDescription vmstate_spapr_tce_table = {
|
||||
static MemoryRegionIOMMUOps spapr_iommu_ops = {
|
||||
.translate = spapr_tce_translate_iommu,
|
||||
.get_min_page_size = spapr_tce_get_min_page_size,
|
||||
.notify_started = spapr_tce_notify_started,
|
||||
.notify_stopped = spapr_tce_notify_stopped,
|
||||
.notify_flag_changed = spapr_tce_notify_flag_changed,
|
||||
};
|
||||
|
||||
static int spapr_tce_table_realize(DeviceState *dev)
|
||||
|
@ -174,10 +174,10 @@ struct MemoryRegionIOMMUOps {
|
||||
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write);
|
||||
/* Returns minimum supported page size */
|
||||
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
|
||||
/* Called when the first notifier is set */
|
||||
void (*notify_started)(MemoryRegion *iommu);
|
||||
/* Called when the last notifier is removed */
|
||||
void (*notify_stopped)(MemoryRegion *iommu);
|
||||
/* Called when IOMMU Notifier flag changed */
|
||||
void (*notify_flag_changed)(MemoryRegion *iommu,
|
||||
IOMMUNotifierFlag old_flags,
|
||||
IOMMUNotifierFlag new_flags);
|
||||
};
|
||||
|
||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||
@ -223,6 +223,7 @@ struct MemoryRegion {
|
||||
unsigned ioeventfd_nb;
|
||||
MemoryRegionIoeventfd *ioeventfds;
|
||||
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
|
||||
IOMMUNotifierFlag iommu_notify_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
29
memory.c
29
memory.c
@ -1414,6 +1414,7 @@ void memory_region_init_iommu(MemoryRegion *mr,
|
||||
mr->iommu_ops = ops,
|
||||
mr->terminates = true; /* then re-forwards */
|
||||
QLIST_INIT(&mr->iommu_notify);
|
||||
mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
|
||||
}
|
||||
|
||||
static void memory_region_finalize(Object *obj)
|
||||
@ -1508,16 +1509,31 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
|
||||
return memory_region_get_dirty_log_mask(mr) & (1 << client);
|
||||
}
|
||||
|
||||
static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
|
||||
{
|
||||
IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
|
||||
IOMMUNotifier *iommu_notifier;
|
||||
|
||||
QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) {
|
||||
flags |= iommu_notifier->notifier_flags;
|
||||
}
|
||||
|
||||
if (flags != mr->iommu_notify_flags &&
|
||||
mr->iommu_ops->notify_flag_changed) {
|
||||
mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags,
|
||||
flags);
|
||||
}
|
||||
|
||||
mr->iommu_notify_flags = flags;
|
||||
}
|
||||
|
||||
void memory_region_register_iommu_notifier(MemoryRegion *mr,
|
||||
IOMMUNotifier *n)
|
||||
{
|
||||
/* We need to register for at least one bitfield */
|
||||
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
|
||||
if (mr->iommu_ops->notify_started &&
|
||||
QLIST_EMPTY(&mr->iommu_notify)) {
|
||||
mr->iommu_ops->notify_started(mr);
|
||||
}
|
||||
QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
|
||||
memory_region_update_iommu_notify_flags(mr);
|
||||
}
|
||||
|
||||
uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
|
||||
@ -1555,10 +1571,7 @@ void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
|
||||
IOMMUNotifier *n)
|
||||
{
|
||||
QLIST_REMOVE(n, node);
|
||||
if (mr->iommu_ops->notify_stopped &&
|
||||
QLIST_EMPTY(&mr->iommu_notify)) {
|
||||
mr->iommu_ops->notify_stopped(mr);
|
||||
}
|
||||
memory_region_update_iommu_notify_flags(mr);
|
||||
}
|
||||
|
||||
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||
|
Loading…
Reference in New Issue
Block a user