Blame SOURCES/kvm-virtio-iommu-Use-recursive-lock-to-avoid-deadlock.patch

29b115
From 881c999e302e7ee1212b47c523a2cf442c549417 Mon Sep 17 00:00:00 2001
29b115
From: Zhenzhong Duan <zhenzhong.duan@intel.com>
29b115
Date: Mon, 13 Jun 2022 14:10:09 +0800
29b115
Subject: [PATCH 02/17] virtio-iommu: Use recursive lock to avoid deadlock
29b115
29b115
RH-Author: Eric Auger <eric.auger@redhat.com>
29b115
RH-MergeRequest: 105: virtio-iommu: Fix bypass mode for assigned devices
29b115
RH-Commit: [2/5] 67dce1eecb49555f728f119f8efac00417ff65bf (eauger1/centos-qemu-kvm)
29b115
RH-Bugzilla: 2100106
29b115
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
29b115
RH-Acked-by: Peter Xu <peterx@redhat.com>
29b115
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
29b115
29b115
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2100106
29b115
29b115
When switching address space with mutex lock hold, mapping will be
29b115
replayed for assigned device. This will trigger relock deadlock.
29b115
29b115
Also release the mutex resource in unrealize routine.
29b115
29b115
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
29b115
Message-Id: <20220613061010.2674054-3-zhenzhong.duan@intel.com>
29b115
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
29b115
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
29b115
(cherry picked from commit 08f2030a2e46f1e93d186b3a683e5caef1df562b)
29b115
Signed-off-by: Eric Auger <eric.auger@redhat.com>
29b115
---
29b115
 hw/virtio/virtio-iommu.c         | 20 +++++++++++---------
29b115
 include/hw/virtio/virtio-iommu.h |  2 +-
29b115
 2 files changed, 12 insertions(+), 10 deletions(-)
29b115
29b115
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
29b115
index 5e99e6c62b..440a1c28a7 100644
29b115
--- a/hw/virtio/virtio-iommu.c
29b115
+++ b/hw/virtio/virtio-iommu.c
29b115
@@ -79,7 +79,7 @@ static bool virtio_iommu_device_bypassed(IOMMUDevice *sdev)
29b115
 
29b115
     sid = virtio_iommu_get_bdf(sdev);
29b115
 
29b115
-    qemu_mutex_lock(&s->mutex);
29b115
+    qemu_rec_mutex_lock(&s->mutex);
29b115
     /* need to check bypass before system reset */
29b115
     if (!s->endpoints) {
29b115
         bypassed = s->config.bypass;
29b115
@@ -94,7 +94,7 @@ static bool virtio_iommu_device_bypassed(IOMMUDevice *sdev)
29b115
     }
29b115
 
29b115
 unlock:
29b115
-    qemu_mutex_unlock(&s->mutex);
29b115
+    qemu_rec_mutex_unlock(&s->mutex);
29b115
     return bypassed;
29b115
 }
29b115
 
29b115
@@ -746,7 +746,7 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)
29b115
             tail.status = VIRTIO_IOMMU_S_DEVERR;
29b115
             goto out;
29b115
         }
29b115
-        qemu_mutex_lock(&s->mutex);
29b115
+        qemu_rec_mutex_lock(&s->mutex);
29b115
         switch (head.type) {
29b115
         case VIRTIO_IOMMU_T_ATTACH:
29b115
             tail.status = virtio_iommu_handle_attach(s, iov, iov_cnt);
29b115
@@ -775,7 +775,7 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)
29b115
         default:
29b115
             tail.status = VIRTIO_IOMMU_S_UNSUPP;
29b115
         }
29b115
-        qemu_mutex_unlock(&s->mutex);
29b115
+        qemu_rec_mutex_unlock(&s->mutex);
29b115
 
29b115
 out:
29b115
         sz = iov_from_buf(elem->in_sg, elem->in_num, 0,
29b115
@@ -863,7 +863,7 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
29b115
     sid = virtio_iommu_get_bdf(sdev);
29b115
 
29b115
     trace_virtio_iommu_translate(mr->parent_obj.name, sid, addr, flag);
29b115
-    qemu_mutex_lock(&s->mutex);
29b115
+    qemu_rec_mutex_lock(&s->mutex);
29b115
 
29b115
     ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(sid));
29b115
     if (!ep) {
29b115
@@ -947,7 +947,7 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
29b115
     trace_virtio_iommu_translate_out(addr, entry.translated_addr, sid);
29b115
 
29b115
 unlock:
29b115
-    qemu_mutex_unlock(&s->mutex);
29b115
+    qemu_rec_mutex_unlock(&s->mutex);
29b115
     return entry;
29b115
 }
29b115
 
29b115
@@ -1036,7 +1036,7 @@ static void virtio_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n)
29b115
 
29b115
     sid = virtio_iommu_get_bdf(sdev);
29b115
 
29b115
-    qemu_mutex_lock(&s->mutex);
29b115
+    qemu_rec_mutex_lock(&s->mutex);
29b115
 
29b115
     if (!s->endpoints) {
29b115
         goto unlock;
29b115
@@ -1050,7 +1050,7 @@ static void virtio_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n)
29b115
     g_tree_foreach(ep->domain->mappings, virtio_iommu_remap, mr);
29b115
 
29b115
 unlock:
29b115
-    qemu_mutex_unlock(&s->mutex);
29b115
+    qemu_rec_mutex_unlock(&s->mutex);
29b115
 }
29b115
 
29b115
 static int virtio_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu_mr,
29b115
@@ -1169,7 +1169,7 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
29b115
     virtio_add_feature(&s->features, VIRTIO_IOMMU_F_PROBE);
29b115
     virtio_add_feature(&s->features, VIRTIO_IOMMU_F_BYPASS_CONFIG);
29b115
 
29b115
-    qemu_mutex_init(&s->mutex);
29b115
+    qemu_rec_mutex_init(&s->mutex);
29b115
 
29b115
     s->as_by_busptr = g_hash_table_new_full(NULL, NULL, NULL, g_free);
29b115
 
29b115
@@ -1197,6 +1197,8 @@ static void virtio_iommu_device_unrealize(DeviceState *dev)
29b115
         g_tree_destroy(s->endpoints);
29b115
     }
29b115
 
29b115
+    qemu_rec_mutex_destroy(&s->mutex);
29b115
+
29b115
     virtio_delete_queue(s->req_vq);
29b115
     virtio_delete_queue(s->event_vq);
29b115
     virtio_cleanup(vdev);
29b115
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
29b115
index 102eeefa73..2ad5ee320b 100644
29b115
--- a/include/hw/virtio/virtio-iommu.h
29b115
+++ b/include/hw/virtio/virtio-iommu.h
29b115
@@ -58,7 +58,7 @@ struct VirtIOIOMMU {
29b115
     ReservedRegion *reserved_regions;
29b115
     uint32_t nb_reserved_regions;
29b115
     GTree *domains;
29b115
-    QemuMutex mutex;
29b115
+    QemuRecMutex mutex;
29b115
     GTree *endpoints;
29b115
     bool boot_bypass;
29b115
 };
29b115
-- 
29b115
2.31.1
29b115