aboutsummaryrefslogtreecommitdiff
path: root/hw/i386/intel_iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i386/intel_iommu.c')
-rw-r--r--hw/i386/intel_iommu.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index a7bf87a19e..3a5bb0bc2e 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -957,6 +957,8 @@ static bool vtd_dev_pt_enabled(VTDAddressSpace *as)
static bool vtd_switch_address_space(VTDAddressSpace *as)
{
bool use_iommu;
+ /* Whether we need to take the BQL on our own */
+ bool take_bql = !qemu_mutex_iothread_locked();
assert(as);
@@ -967,6 +969,15 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
VTD_PCI_FUNC(as->devfn),
use_iommu);
+ /*
+ * It's possible that we reach here without BQL, e.g., when called
+ * from vtd_pt_enable_fast_path(). However the memory APIs need
+ * it. We'd better make sure we have had it already, or, take it.
+ */
+ if (take_bql) {
+ qemu_mutex_lock_iothread();
+ }
+
/* Turn off first then on the other */
if (use_iommu) {
memory_region_set_enabled(&as->sys_alias, false);
@@ -976,6 +987,10 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
memory_region_set_enabled(&as->sys_alias, true);
}
+ if (take_bql) {
+ qemu_mutex_unlock_iothread();
+ }
+
return use_iommu;
}