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

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