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);
|
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
|
||||||
|
|
||||||
@ -1080,7 +1082,7 @@ static void amdvi_init(AMDVIState *s)
|
|||||||
amdvi_iotlb_reset(s);
|
amdvi_iotlb_reset(s);
|
||||||
|
|
||||||
s->iommu_ops.translate = amdvi_translate;
|
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->devtab_len = 0;
|
||||||
s->cmdbuf_len = 0;
|
s->cmdbuf_len = 0;
|
||||||
s->cmdbuf_head = 0;
|
s->cmdbuf_head = 0;
|
||||||
|
@ -1974,7 +1974,9 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
|
|||||||
return ret;
|
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);
|
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);
|
memset(s->womask, 0, DMAR_REG_SIZE);
|
||||||
|
|
||||||
s->iommu_ops.translate = vtd_iommu_translate;
|
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 = 0;
|
||||||
s->root_extended = false;
|
s->root_extended = false;
|
||||||
s->dmar_enabled = 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;
|
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)
|
if (old == IOMMU_NOTIFIER_NONE && new != IOMMU_NOTIFIER_NONE) {
|
||||||
{
|
spapr_tce_set_need_vfio(tbl, true);
|
||||||
spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), false);
|
} 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)
|
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 = {
|
static MemoryRegionIOMMUOps spapr_iommu_ops = {
|
||||||
.translate = spapr_tce_translate_iommu,
|
.translate = spapr_tce_translate_iommu,
|
||||||
.get_min_page_size = spapr_tce_get_min_page_size,
|
.get_min_page_size = spapr_tce_get_min_page_size,
|
||||||
.notify_started = spapr_tce_notify_started,
|
.notify_flag_changed = spapr_tce_notify_flag_changed,
|
||||||
.notify_stopped = spapr_tce_notify_stopped,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int spapr_tce_table_realize(DeviceState *dev)
|
static int spapr_tce_table_realize(DeviceState *dev)
|
||||||
|
@ -174,10 +174,10 @@ struct MemoryRegionIOMMUOps {
|
|||||||
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write);
|
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write);
|
||||||
/* Returns minimum supported page size */
|
/* Returns minimum supported page size */
|
||||||
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
|
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
|
||||||
/* Called when the first notifier is set */
|
/* Called when IOMMU Notifier flag changed */
|
||||||
void (*notify_started)(MemoryRegion *iommu);
|
void (*notify_flag_changed)(MemoryRegion *iommu,
|
||||||
/* Called when the last notifier is removed */
|
IOMMUNotifierFlag old_flags,
|
||||||
void (*notify_stopped)(MemoryRegion *iommu);
|
IOMMUNotifierFlag new_flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||||
@ -223,6 +223,7 @@ struct MemoryRegion {
|
|||||||
unsigned ioeventfd_nb;
|
unsigned ioeventfd_nb;
|
||||||
MemoryRegionIoeventfd *ioeventfds;
|
MemoryRegionIoeventfd *ioeventfds;
|
||||||
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
|
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->iommu_ops = ops,
|
||||||
mr->terminates = true; /* then re-forwards */
|
mr->terminates = true; /* then re-forwards */
|
||||||
QLIST_INIT(&mr->iommu_notify);
|
QLIST_INIT(&mr->iommu_notify);
|
||||||
|
mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void memory_region_finalize(Object *obj)
|
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);
|
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,
|
void memory_region_register_iommu_notifier(MemoryRegion *mr,
|
||||||
IOMMUNotifier *n)
|
IOMMUNotifier *n)
|
||||||
{
|
{
|
||||||
/* We need to register for at least one bitfield */
|
/* We need to register for at least one bitfield */
|
||||||
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
|
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);
|
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)
|
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)
|
IOMMUNotifier *n)
|
||||||
{
|
{
|
||||||
QLIST_REMOVE(n, node);
|
QLIST_REMOVE(n, node);
|
||||||
if (mr->iommu_ops->notify_stopped &&
|
memory_region_update_iommu_notify_flags(mr);
|
||||||
QLIST_EMPTY(&mr->iommu_notify)) {
|
|
||||||
mr->iommu_ops->notify_stopped(mr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_region_notify_iommu(MemoryRegion *mr,
|
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||||
|
Loading…
Reference in New Issue
Block a user