From: Xiong Zhang <xiong.y.zhang@intel.com>
Date: Fri, 13 Apr 2018 10:26:16 +0800
Subject: drm/i915/gvt: Dereference msi eventfd_ctx when it isn't used anymore
Git-commit: d54e79340ff8d65b6c63ac278158add2fe211fd0
Patch-mainline: v4.18-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166
kvmgt get msi eventfd_ctx at qemu vfio set irq eventfd, then
msi eventfd_ctx should be put at some point.
The first point is kvmgt handle qemu vfio_disable_irqindex()
call which has DATA_NONE and ACTION_TRIGGER in flags.
If qemu doesn't call vfio_disable_irqindex(), the second point
is vgpu release function.
v2: Don't inject msi interrupt into guest if eventfd_ctx is dereferenced
Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
drivers/gpu/drm/i915/gvt/kvmgt.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -583,6 +583,17 @@ out:
return ret;
}
+static void intel_vgpu_release_msi_eventfd_ctx(struct intel_vgpu *vgpu)
+{
+ struct eventfd_ctx *trigger;
+
+ trigger = vgpu->vdev.msi_trigger;
+ if (trigger) {
+ eventfd_ctx_put(trigger);
+ vgpu->vdev.msi_trigger = NULL;
+ }
+}
+
static void __intel_vgpu_release(struct intel_vgpu *vgpu)
{
struct kvmgt_guest_info *info;
@@ -607,6 +618,8 @@ static void __intel_vgpu_release(struct
info = (struct kvmgt_guest_info *)vgpu->handle;
kvmgt_guest_exit(info);
+ intel_vgpu_release_msi_eventfd_ctx(vgpu);
+
vgpu->vdev.kvm = NULL;
vgpu->handle = 0;
}
@@ -987,7 +1000,8 @@ static int intel_vgpu_set_msi_trigger(st
return PTR_ERR(trigger);
}
vgpu->vdev.msi_trigger = trigger;
- }
+ } else if ((flags & VFIO_IRQ_SET_DATA_NONE) && !count)
+ intel_vgpu_release_msi_eventfd_ctx(vgpu);
return 0;
}
@@ -1592,6 +1606,18 @@ static int kvmgt_inject_msi(unsigned lon
info = (struct kvmgt_guest_info *)handle;
vgpu = info->vgpu;
+ /*
+ * When guest is poweroff, msi_trigger is set to NULL, but vgpu's
+ * config and mmio register isn't restored to default during guest
+ * poweroff. If this vgpu is still used in next vm, this vgpu's pipe
+ * may be enabled, then once this vgpu is active, it will get inject
+ * vblank interrupt request. But msi_trigger is null until msi is
+ * enabled by guest. so if msi_trigger is null, success is still
+ * returned and don't inject interrupt into guest.
+ */
+ if (vgpu->vdev.msi_trigger == NULL)
+ return 0;
+
if (eventfd_signal(vgpu->vdev.msi_trigger, 1) == 1)
return 0;