aboutsummaryrefslogtreecommitdiff
path: root/hw/arm/smmu-common.c
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2018-06-26 17:50:42 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-06-26 17:50:42 +0100
commit832e4222c82071e4399cffdecd605abed5ac0c27 (patch)
treed48f9f61abf26ee9b2bd77aa3fbfca3f3d4213b8 /hw/arm/smmu-common.c
parentcc27ed81cf11d5b7ffc7eca9f31dfcd82c983c56 (diff)
hw/arm/smmuv3: Add notifications on invalidation
On TLB invalidation commands, let's call registered IOMMU notifiers. Those can only be UNMAP notifiers. SMMUv3 does not support notification on MAP (VFIO). This patch allows vhost use case where IOTLB API is notified on each guest IOTLB invalidation. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1529653501-15358-5-git-send-email-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/smmu-common.c')
-rw-r--r--hw/arm/smmu-common.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index f66e444f6f..3098915d07 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -385,6 +385,40 @@ static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
return (k1->asid == k2->asid) && (k1->iova == k2->iova);
}
+/* Unmap the whole notifier's range */
+static void smmu_unmap_notifier_range(IOMMUNotifier *n)
+{
+ IOMMUTLBEntry entry;
+
+ entry.target_as = &address_space_memory;
+ entry.iova = n->start;
+ entry.perm = IOMMU_NONE;
+ entry.addr_mask = n->end - n->start;
+
+ memory_region_notify_one(n, &entry);
+}
+
+/* Unmap all notifiers attached to @mr */
+inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
+{
+ IOMMUNotifier *n;
+
+ trace_smmu_inv_notifiers_mr(mr->parent_obj.name);
+ IOMMU_NOTIFIER_FOREACH(n, mr) {
+ smmu_unmap_notifier_range(n);
+ }
+}
+
+/* Unmap all notifiers of all mr's */
+void smmu_inv_notifiers_all(SMMUState *s)
+{
+ SMMUNotifierNode *node;
+
+ QLIST_FOREACH(node, &s->notifiers_list, next) {
+ smmu_inv_notifiers_mr(&node->sdev->iommu);
+ }
+}
+
static void smmu_base_realize(DeviceState *dev, Error **errp)
{
SMMUState *s = ARM_SMMU(dev);