|
@@ -123,6 +123,12 @@ static int gvt_dma_map_page(struct intel_vgpu *vgpu, unsigned long gfn,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ if (!pfn_valid(pfn)) {
|
|
|
+ gvt_vgpu_err("pfn 0x%lx is not mem backed\n", pfn);
|
|
|
+ vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), &gfn, 1);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
/* Setup DMA mapping. */
|
|
|
page = pfn_to_page(pfn);
|
|
|
*dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE,
|
|
@@ -583,6 +589,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 +624,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;
|
|
|
}
|
|
@@ -987,7 +1006,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;
|
|
|
}
|
|
@@ -1592,6 +1612,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;
|
|
|
|