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: Si-Wei Liu <si-wei.liu@oracle.com> Tested-by: Stefano Garzarella <sgarzare@redhat.com> Message-Id: <1697880319-4937-8-git-send-email-si-wei.liu@oracle.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Lei Yang <leiyang@redhat.com>
This commit is contained in:
parent
2eacf4b5e3
commit
86f6c224c9
@ -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,11 +151,13 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim)
|
||||
&vdpasim->iommu_lock);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
@ -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 @@ err:
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user