[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [RFC 10/20] memory: Add IOMMUConfigNotifier
From: |
Eric Auger |
Subject: |
[Qemu-arm] [RFC 10/20] memory: Add IOMMUConfigNotifier |
Date: |
Sat, 1 Sep 2018 16:23:02 +0200 |
With this patch, an IOMMUNotifier can now be either
an IOTLB notifier or a config notifier. A config notifier
is supposed to be called on guest translation config change.
This gives host a chance to update the physical IOMMU
configuration so that is consistent with the guest view.
The notifier is passed an iommu_guest_stage_config struct.
We introduce the associated helpers, iommu_config_notifier_init,
memory_region_config_notify_iommu
Signed-off-by: Eric Auger <address@hidden>
---
hw/vfio/common.c | 14 ++++++++----
include/exec/memory.h | 52 +++++++++++++++++++++++++++++++++++++++++--
memory.c | 32 ++++++++++++++++++++++++--
3 files changed, 90 insertions(+), 8 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b6673fcf49..7bd3cc250d 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -624,10 +624,16 @@ static void vfio_listener_region_del(MemoryListener
*listener,
VFIOGuestIOMMU *giommu;
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
- if (MEMORY_REGION(giommu->iommu) == section->mr &&
- giommu->n.iotlb_notifier.start ==
section->offset_within_region) {
- memory_region_unregister_iommu_notifier(section->mr,
- &giommu->n);
+ if (MEMORY_REGION(giommu->iommu) == section->mr) {
+ if (is_iommu_iotlb_notifier(&giommu->n) &&
+ giommu->n.iotlb_notifier.start ==
+ section->offset_within_region) {
+ memory_region_unregister_iommu_notifier(section->mr,
+ &giommu->n);
+ } else if (is_iommu_config_notifier(&giommu->n)) {
+ memory_region_unregister_iommu_notifier(section->mr,
+ &giommu->n);
+ }
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
break;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 5ef9bf6d21..e89fd95fc5 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -84,13 +84,23 @@ typedef enum {
IOMMU_NOTIFIER_UNMAP = 0x1,
/* Notify entry changes (newly created entries) */
IOMMU_NOTIFIER_MAP = 0x2,
+ /* Notify stage 1 config changes */
+ IOMMU_NOTIFIER_S1_CFG = 0x4,
} IOMMUNotifierFlag;
#define IOMMU_NOTIFIER_IOTLB_ALL (IOMMU_NOTIFIER_MAP | IOMMU_NOTIFIER_UNMAP)
+#define IOMMU_NOTIFIER_CONFIG_ALL (IOMMU_NOTIFIER_S1_CFG)
+
+typedef enum {
+ IOMMU_ARM_SMMUV3 = 0x1,
+} IOMMUStage1ConfigType;
struct IOMMUNotifier;
+struct iommu_guest_stage_config;
typedef void (*IOMMUNotify)(struct IOMMUNotifier *notifier,
IOMMUTLBEntry *data);
+typedef void (*IOMMUConfigNotify)(struct IOMMUNotifier *notifier,
+ struct iommu_guest_stage_config *cfg);
typedef struct IOMMUIOLTBNotifier {
IOMMUNotify notify;
@@ -99,9 +109,16 @@ typedef struct IOMMUIOLTBNotifier {
hwaddr end;
} IOMMUIOLTBNotifier;
+typedef struct IOMMUConfigNotifier {
+ IOMMUConfigNotify notify;
+} IOMMUConfigNotifier;
+
struct IOMMUNotifier {
IOMMUNotifierFlag notifier_flags;
- IOMMUIOLTBNotifier iotlb_notifier;
+ union {
+ IOMMUIOLTBNotifier iotlb_notifier;
+ IOMMUConfigNotifier config_notifier;
+ };
int iommu_idx;
QLIST_ENTRY(IOMMUNotifier) node;
};
@@ -143,6 +160,15 @@ static inline void iommu_iotlb_notifier_init(IOMMUNotifier
*n, IOMMUNotify fn,
n->iommu_idx = iommu_idx;
}
+static inline void iommu_config_notifier_init(IOMMUNotifier *n,
+ IOMMUConfigNotify fn,
+ int iommu_idx)
+{
+ n->notifier_flags = IOMMU_NOTIFIER_S1_CFG;
+ n->iommu_idx = iommu_idx;
+ n->config_notifier.notify = fn;
+}
+
/*
* Memory region callbacks
*/
@@ -639,6 +665,17 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
uint64_t length,
void *host),
Error **errp);
+
+static inline bool is_iommu_iotlb_notifier(IOMMUNotifier *n)
+{
+ return n->notifier_flags & IOMMU_NOTIFIER_IOTLB_ALL;
+}
+
+static inline bool is_iommu_config_notifier(IOMMUNotifier *n)
+{
+ return n->notifier_flags & IOMMU_NOTIFIER_CONFIG_ALL;
+}
+
#ifdef __linux__
/**
@@ -1045,6 +1082,17 @@ void memory_region_iotlb_notify_iommu(IOMMUMemoryRegion
*iommu_mr,
int iommu_idx,
IOMMUTLBEntry entry);
+/**
+ * memory_region_config_notify_iommu: notify a change in a translation
+ * configuration structure.
+ * @iommu_mr: the memory region that was changed
+ * @iommu_idx: the IOMMU index for the translation table which has changed
+ * @config: new guest config
+ */
+void memory_region_config_notify_iommu(IOMMUMemoryRegion *iommu_mr,
+ int iommu_idx,
+ struct iommu_guest_stage_config
*config);
+
/**
* memory_region_iotlb_notify_one: notify a change in an IOMMU translation
* entry to a single notifier
@@ -1062,7 +1110,7 @@ void memory_region_iotlb_notify_one(IOMMUNotifier
*notifier,
/**
* memory_region_register_iommu_notifier: register a notifier for changes to
- * IOMMU translation entries.
+ * IOMMU translation entries or translation config settings.
*
* @mr: the memory region to observe
* @n: the IOMMUNotifier to be added; the notify callback receives a
diff --git a/memory.c b/memory.c
index 8ee5cbdbad..ea2a09b0dd 100644
--- a/memory.c
+++ b/memory.c
@@ -49,6 +49,8 @@ static GHashTable *flat_views;
typedef struct AddrRange AddrRange;
+struct iommu_guest_stage_config;
+
/*
* Note that signed integers are needed for negative offsetting in aliases
* (large MemoryRegion::alias_offset).
@@ -1800,7 +1802,9 @@ void memory_region_register_iommu_notifier(MemoryRegion
*mr,
/* We need to register for at least one bitfield */
iommu_mr = IOMMU_MEMORY_REGION(mr);
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
- assert(n->iotlb_notifier.start <= n->iotlb_notifier.end);
+ if (is_iommu_iotlb_notifier(n)) {
+ assert(n->iotlb_notifier.start <= n->iotlb_notifier.end);
+ }
assert(n->iommu_idx >= 0 &&
n->iommu_idx < memory_region_iommu_num_indexes(iommu_mr));
@@ -1870,6 +1874,13 @@ void
memory_region_unregister_iommu_notifier(MemoryRegion *mr,
memory_region_update_iommu_notify_flags(iommu_mr);
}
+static void
+memory_region_config_notify_one(IOMMUNotifier *notifier,
+ struct iommu_guest_stage_config *cfg)
+{
+ notifier->config_notifier.notify(notifier, cfg);
+}
+
void memory_region_iotlb_notify_one(IOMMUNotifier *notifier,
IOMMUTLBEntry *entry)
{
@@ -1904,12 +1915,29 @@ void memory_region_iotlb_notify_iommu(IOMMUMemoryRegion
*iommu_mr,
assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
- if (iommu_notifier->iommu_idx == iommu_idx) {
+ if (iommu_notifier->iommu_idx == iommu_idx &&
+ is_iommu_iotlb_notifier(iommu_notifier)) {
memory_region_iotlb_notify_one(iommu_notifier, &entry);
}
}
}
+void memory_region_config_notify_iommu(IOMMUMemoryRegion *iommu_mr,
+ int iommu_idx,
+ struct iommu_guest_stage_config *config)
+{
+ IOMMUNotifier *iommu_notifier;
+
+ assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
+
+ IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
+ if (iommu_notifier->iommu_idx == iommu_idx &&
+ is_iommu_config_notifier(iommu_notifier)) {
+ memory_region_config_notify_one(iommu_notifier, config);
+ }
+ }
+}
+
int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
enum IOMMUMemoryRegionAttr attr,
void *data)
--
2.17.1
- [Qemu-arm] [RFC 05/20] hw/arm/smmuv3: Implement get_attr API to report IOMMU_ATTR_VFIO_NESTED, (continued)
- [Qemu-arm] [RFC 05/20] hw/arm/smmuv3: Implement get_attr API to report IOMMU_ATTR_VFIO_NESTED, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 20/20] hw/arm/smmuv3: Remove warning about unsupported MAP notifiers, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 04/20] memory: add IOMMU_ATTR_VFIO_NESTED IOMMU memory region attribute, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 19/20] vfio/pci: Always set up MSI route before enabling vectors, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 18/20] target/arm/kvm: Notifies IOMMU on MSI stage 1 binding, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 16/20] hw/vfio/common: Register specific nested mode notifiers and memory_listener, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 15/20] hw/vfio/common: Introduce vfio_dma_(un)map_ram_section helpers, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 17/20] hw/vfio/common: Register MAP notifier for MSI binding, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 14/20] hw/vfio/common: Introduce vfio_alloc_guest_iommu helper, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 13/20] hw/arm/smmuv3: Notify on config changes, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 10/20] memory: Add IOMMUConfigNotifier,
Eric Auger <=
- [Qemu-arm] [RFC 11/20] hw/arm/smmuv3: Store s1ctrptr in translation config data, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 12/20] hw/arm/smmuv3: Implement dummy replay, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 08/20] memory: Introduce IOMMUIOLTBNotifier, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 09/20] memory: rename memory_region notify_iommu, notify_one, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 07/20] hw/vfio/common: Force nested if iommu requires it, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 06/20] hw/vfio/common: Refactor container initialization, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 03/20] linux-headers: Partial header update, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 02/20] update-linux-headers: Import iommu.h, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 01/20] hw/arm/smmu-common: Fix the name of the iommu memory regions, Eric Auger, 2018/09/01