Commit 86f6c224 authored by Si-Wei Liu's avatar Si-Wei Liu Committed by Michael S. Tsirkin
Browse files

vdpa_sim: implement .reset_map support



In order to reduce excessive memory mapping cost in live migration and
VM reboot, it is desirable to decouple the vhost-vdpa IOTLB abstraction
from the virtio device life cycle, i.e. mappings can be kept intact
across virtio device reset. Leverage the .reset_map callback, which is
meant to destroy the iotlb on the given ASID and recreate the 1:1
passthrough/identity mapping. To be consistent, the mapping on device
creation is initiailized to passthrough/identity with PA 1:1 mapped as
IOVA. With this the device .reset op doesn't have to maintain and clean
up memory mappings by itself.

Additionally, implement .compat_reset to cater for older userspace,
which may wish to see mapping to be cleared during reset.

Signed-off-by: default avatarSi-Wei Liu <si-wei.liu@oracle.com>
Tested-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Message-Id: <1697880319-4937-8-git-send-email-si-wei.liu@oracle.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Tested-by: default avatarLei Yang <leiyang@redhat.com>
parent 2eacf4b5
Loading
Loading
Loading
Loading
+43 −9
Original line number Diff line number Diff line
@@ -139,7 +139,7 @@ static void vdpasim_vq_reset(struct vdpasim *vdpasim,
	vq->vring.notify = NULL;
}

static void vdpasim_do_reset(struct vdpasim *vdpasim)
static void vdpasim_do_reset(struct vdpasim *vdpasim, u32 flags)
{
	int i;

@@ -151,12 +151,14 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim)
				 &vdpasim->iommu_lock);
	}

	if (flags & VDPA_RESET_F_CLEAN_MAP) {
		for (i = 0; i < vdpasim->dev_attr.nas; i++) {
			vhost_iotlb_reset(&vdpasim->iommu[i]);
			vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX,
					      0, VHOST_MAP_RW);
			vdpasim->iommu_pt[i] = true;
		}
	}

	vdpasim->running = true;
	spin_unlock(&vdpasim->iommu_lock);
@@ -259,8 +261,12 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
	if (!vdpasim->iommu_pt)
		goto err_iommu;

	for (i = 0; i < vdpasim->dev_attr.nas; i++)
	for (i = 0; i < vdpasim->dev_attr.nas; i++) {
		vhost_iotlb_init(&vdpasim->iommu[i], max_iotlb_entries, 0);
		vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, 0,
				      VHOST_MAP_RW);
		vdpasim->iommu_pt[i] = true;
	}

	for (i = 0; i < dev_attr->nvqs; i++)
		vringh_set_iotlb(&vdpasim->vqs[i].vring, &vdpasim->iommu[0],
@@ -480,18 +486,23 @@ static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status)
	mutex_unlock(&vdpasim->mutex);
}

static int vdpasim_reset(struct vdpa_device *vdpa)
static int vdpasim_compat_reset(struct vdpa_device *vdpa, u32 flags)
{
	struct vdpasim *vdpasim = vdpa_to_sim(vdpa);

	mutex_lock(&vdpasim->mutex);
	vdpasim->status = 0;
	vdpasim_do_reset(vdpasim);
	vdpasim_do_reset(vdpasim, flags);
	mutex_unlock(&vdpasim->mutex);

	return 0;
}

static int vdpasim_reset(struct vdpa_device *vdpa)
{
	return vdpasim_compat_reset(vdpa, 0);
}

static int vdpasim_suspend(struct vdpa_device *vdpa)
{
	struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
@@ -637,6 +648,25 @@ static int vdpasim_set_map(struct vdpa_device *vdpa, unsigned int asid,
	return ret;
}

static int vdpasim_reset_map(struct vdpa_device *vdpa, unsigned int asid)
{
	struct vdpasim *vdpasim = vdpa_to_sim(vdpa);

	if (asid >= vdpasim->dev_attr.nas)
		return -EINVAL;

	spin_lock(&vdpasim->iommu_lock);
	if (vdpasim->iommu_pt[asid])
		goto out;
	vhost_iotlb_reset(&vdpasim->iommu[asid]);
	vhost_iotlb_add_range(&vdpasim->iommu[asid], 0, ULONG_MAX,
			      0, VHOST_MAP_RW);
	vdpasim->iommu_pt[asid] = true;
out:
	spin_unlock(&vdpasim->iommu_lock);
	return 0;
}

static int vdpasim_bind_mm(struct vdpa_device *vdpa, struct mm_struct *mm)
{
	struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
@@ -749,6 +779,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
	.get_status             = vdpasim_get_status,
	.set_status             = vdpasim_set_status,
	.reset			= vdpasim_reset,
	.compat_reset		= vdpasim_compat_reset,
	.suspend		= vdpasim_suspend,
	.resume			= vdpasim_resume,
	.get_config_size        = vdpasim_get_config_size,
@@ -759,6 +790,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
	.set_group_asid         = vdpasim_set_group_asid,
	.dma_map                = vdpasim_dma_map,
	.dma_unmap              = vdpasim_dma_unmap,
	.reset_map              = vdpasim_reset_map,
	.bind_mm		= vdpasim_bind_mm,
	.unbind_mm		= vdpasim_unbind_mm,
	.free                   = vdpasim_free,
@@ -787,6 +819,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = {
	.get_status             = vdpasim_get_status,
	.set_status             = vdpasim_set_status,
	.reset			= vdpasim_reset,
	.compat_reset		= vdpasim_compat_reset,
	.suspend		= vdpasim_suspend,
	.resume			= vdpasim_resume,
	.get_config_size        = vdpasim_get_config_size,
@@ -796,6 +829,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = {
	.get_iova_range         = vdpasim_get_iova_range,
	.set_group_asid         = vdpasim_set_group_asid,
	.set_map                = vdpasim_set_map,
	.reset_map              = vdpasim_reset_map,
	.bind_mm		= vdpasim_bind_mm,
	.unbind_mm		= vdpasim_unbind_mm,
	.free                   = vdpasim_free,