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