Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 364fb6b7 authored by Jike Song's avatar Jike Song Committed by Zhenyu Wang
Browse files

drm/i915/gvt/kvmgt: prevent double-release of vgpu



The release action might be triggered from either user's closing
mdev or the detaching event of kvm and vfio_group, so this patch
introduces an atomic to prevent double-release.

Signed-off-by: default avatarJike Song <jike.song@intel.com>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
parent faaaa53b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ struct intel_vgpu {
		struct notifier_block group_notifier;
		struct kvm *kvm;
		struct work_struct release_work;
		atomic_t released;
	} vdev;
#endif
};
+21 −3
Original line number Diff line number Diff line
@@ -500,7 +500,16 @@ static int intel_vgpu_open(struct mdev_device *mdev)
		goto undo_iommu;
	}

	return kvmgt_guest_init(mdev);
	ret = kvmgt_guest_init(mdev);
	if (ret)
		goto undo_group;

	atomic_set(&vgpu->vdev.released, 0);
	return ret;

undo_group:
	vfio_unregister_notifier(&mdev->dev, VFIO_GROUP_NOTIFY,
					&vgpu->vdev.group_notifier);

undo_iommu:
	vfio_unregister_notifier(&mdev->dev, VFIO_IOMMU_NOTIFY,
@@ -512,17 +521,26 @@ static int intel_vgpu_open(struct mdev_device *mdev)
static void __intel_vgpu_release(struct intel_vgpu *vgpu)
{
	struct kvmgt_guest_info *info;
	int ret;

	if (!handle_valid(vgpu->handle))
		return;

	vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_IOMMU_NOTIFY,
	if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1))
		return;

	ret = vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_IOMMU_NOTIFY,
					&vgpu->vdev.iommu_notifier);
	vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_GROUP_NOTIFY,
	WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret);

	ret = vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_GROUP_NOTIFY,
					&vgpu->vdev.group_notifier);
	WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret);

	info = (struct kvmgt_guest_info *)vgpu->handle;
	kvmgt_guest_exit(info);

	vgpu->vdev.kvm = NULL;
	vgpu->handle = 0;
}