drm/i915/gvt: Dereference msi eventfd_ctx when it isn't used anymore

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>
This commit is contained in:
Xiong Zhang 2018-04-13 10:26:16 +08:00 committed by Zhenyu Wang
parent 2f24636b4b
commit d54e79340f
1 changed files with 27 additions and 1 deletions

View File

@ -566,6 +566,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;
@ -590,6 +601,8 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
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;
}
@ -970,7 +983,8 @@ static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,
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;
}
@ -1566,6 +1580,18 @@ static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
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;