aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2025-02-18 19:25:32 +0100
committerMichael S. Tsirkin <mst@redhat.com>2025-02-21 07:21:25 -0500
commit2aaf48bcf27d8b3da5b30af6c1ced464d3df30f7 (patch)
treefe7c05c2311b111aa5f0ab4f77fe08661fca9d76
parentd261b84d354a41a38336af813f92f636d3fb3f78 (diff)
downloadqemu-2aaf48bcf27d8b3da5b30af6c1ced464d3df30f7.zip
qemu-2aaf48bcf27d8b3da5b30af6c1ced464d3df30f7.tar.gz
qemu-2aaf48bcf27d8b3da5b30af6c1ced464d3df30f7.tar.bz2
hw/i386/intel-iommu: Migrate to 3-phase reset
Currently the IOMMU may be reset before the devices it protects. For example this happens with virtio devices but also with VFIO devices. In this latter case this produces spurious translation faults on host. Let's use 3-phase reset mechanism and reset the IOMMU on exit phase after all DMA capable devices have been reset on 'enter' or 'hold' phase. Signed-off-by: Eric Auger <eric.auger@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Jason Wang <jasowang@redhat.com> Zhenzhong Duan <zhenzhong.duan@intel.com> Message-Id: <20250218182737.76722-3-eric.auger@redhat.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/i386/intel_iommu.c12
-rw-r--r--hw/i386/trace-events1
2 files changed, 10 insertions, 3 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index f366c22..a5cf2d0 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -4697,10 +4697,11 @@ static void vtd_init(IntelIOMMUState *s)
/* Should not reset address_spaces when reset because devices will still use
* the address space they got at first (won't ask the bus again).
*/
-static void vtd_reset(DeviceState *dev)
+static void vtd_reset_exit(Object *obj, ResetType type)
{
- IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev);
+ IntelIOMMUState *s = INTEL_IOMMU_DEVICE(obj);
+ trace_vtd_reset_exit();
vtd_init(s);
vtd_address_space_refresh_all(s);
}
@@ -4864,8 +4865,13 @@ static void vtd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
X86IOMMUClass *x86_class = X86_IOMMU_DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
- device_class_set_legacy_reset(dc, vtd_reset);
+ /*
+ * Use 'exit' reset phase to make sure all DMA requests
+ * have been quiesced during 'enter' or 'hold' phase
+ */
+ rc->phases.exit = vtd_reset_exit;
dc->vmsd = &vtd_vmstate;
device_class_set_props(dc, vtd_properties);
dc->hotpluggable = false;
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 53c02d7..ac9e1a1 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -68,6 +68,7 @@ vtd_frr_new(int index, uint64_t hi, uint64_t lo) "index %d high 0x%"PRIx64" low
vtd_warn_invalid_qi_tail(uint16_t tail) "tail 0x%"PRIx16
vtd_warn_ir_vector(uint16_t sid, int index, int vec, int target) "sid 0x%"PRIx16" index %d vec %d (should be: %d)"
vtd_warn_ir_trigger(uint16_t sid, int index, int trig, int target) "sid 0x%"PRIx16" index %d trigger %d (should be: %d)"
+vtd_reset_exit(void) ""
# amd_iommu.c
amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32