Skip to content

Commit 86f6c22

Browse files
siwliu-kernelmstsirkin
authored andcommitted
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 <[email protected]> Tested-by: Stefano Garzarella <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> Tested-by: Lei Yang <[email protected]>
1 parent 2eacf4b commit 86f6c22

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

drivers/vdpa/vdpa_sim/vdpa_sim.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ static void vdpasim_vq_reset(struct vdpasim *vdpasim,
139139
vq->vring.notify = NULL;
140140
}
141141

142-
static void vdpasim_do_reset(struct vdpasim *vdpasim)
142+
static void vdpasim_do_reset(struct vdpasim *vdpasim, u32 flags)
143143
{
144144
int i;
145145

@@ -151,11 +151,13 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim)
151151
&vdpasim->iommu_lock);
152152
}
153153

154-
for (i = 0; i < vdpasim->dev_attr.nas; i++) {
155-
vhost_iotlb_reset(&vdpasim->iommu[i]);
156-
vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX,
157-
0, VHOST_MAP_RW);
158-
vdpasim->iommu_pt[i] = true;
154+
if (flags & VDPA_RESET_F_CLEAN_MAP) {
155+
for (i = 0; i < vdpasim->dev_attr.nas; i++) {
156+
vhost_iotlb_reset(&vdpasim->iommu[i]);
157+
vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX,
158+
0, VHOST_MAP_RW);
159+
vdpasim->iommu_pt[i] = true;
160+
}
159161
}
160162

161163
vdpasim->running = true;
@@ -259,8 +261,12 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
259261
if (!vdpasim->iommu_pt)
260262
goto err_iommu;
261263

262-
for (i = 0; i < vdpasim->dev_attr.nas; i++)
264+
for (i = 0; i < vdpasim->dev_attr.nas; i++) {
263265
vhost_iotlb_init(&vdpasim->iommu[i], max_iotlb_entries, 0);
266+
vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, 0,
267+
VHOST_MAP_RW);
268+
vdpasim->iommu_pt[i] = true;
269+
}
264270

265271
for (i = 0; i < dev_attr->nvqs; i++)
266272
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)
480486
mutex_unlock(&vdpasim->mutex);
481487
}
482488

483-
static int vdpasim_reset(struct vdpa_device *vdpa)
489+
static int vdpasim_compat_reset(struct vdpa_device *vdpa, u32 flags)
484490
{
485491
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
486492

487493
mutex_lock(&vdpasim->mutex);
488494
vdpasim->status = 0;
489-
vdpasim_do_reset(vdpasim);
495+
vdpasim_do_reset(vdpasim, flags);
490496
mutex_unlock(&vdpasim->mutex);
491497

492498
return 0;
493499
}
494500

501+
static int vdpasim_reset(struct vdpa_device *vdpa)
502+
{
503+
return vdpasim_compat_reset(vdpa, 0);
504+
}
505+
495506
static int vdpasim_suspend(struct vdpa_device *vdpa)
496507
{
497508
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
@@ -637,6 +648,25 @@ static int vdpasim_set_map(struct vdpa_device *vdpa, unsigned int asid,
637648
return ret;
638649
}
639650

651+
static int vdpasim_reset_map(struct vdpa_device *vdpa, unsigned int asid)
652+
{
653+
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
654+
655+
if (asid >= vdpasim->dev_attr.nas)
656+
return -EINVAL;
657+
658+
spin_lock(&vdpasim->iommu_lock);
659+
if (vdpasim->iommu_pt[asid])
660+
goto out;
661+
vhost_iotlb_reset(&vdpasim->iommu[asid]);
662+
vhost_iotlb_add_range(&vdpasim->iommu[asid], 0, ULONG_MAX,
663+
0, VHOST_MAP_RW);
664+
vdpasim->iommu_pt[asid] = true;
665+
out:
666+
spin_unlock(&vdpasim->iommu_lock);
667+
return 0;
668+
}
669+
640670
static int vdpasim_bind_mm(struct vdpa_device *vdpa, struct mm_struct *mm)
641671
{
642672
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
@@ -749,6 +779,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
749779
.get_status = vdpasim_get_status,
750780
.set_status = vdpasim_set_status,
751781
.reset = vdpasim_reset,
782+
.compat_reset = vdpasim_compat_reset,
752783
.suspend = vdpasim_suspend,
753784
.resume = vdpasim_resume,
754785
.get_config_size = vdpasim_get_config_size,
@@ -759,6 +790,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
759790
.set_group_asid = vdpasim_set_group_asid,
760791
.dma_map = vdpasim_dma_map,
761792
.dma_unmap = vdpasim_dma_unmap,
793+
.reset_map = vdpasim_reset_map,
762794
.bind_mm = vdpasim_bind_mm,
763795
.unbind_mm = vdpasim_unbind_mm,
764796
.free = vdpasim_free,
@@ -787,6 +819,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = {
787819
.get_status = vdpasim_get_status,
788820
.set_status = vdpasim_set_status,
789821
.reset = vdpasim_reset,
822+
.compat_reset = vdpasim_compat_reset,
790823
.suspend = vdpasim_suspend,
791824
.resume = vdpasim_resume,
792825
.get_config_size = vdpasim_get_config_size,
@@ -796,6 +829,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = {
796829
.get_iova_range = vdpasim_get_iova_range,
797830
.set_group_asid = vdpasim_set_group_asid,
798831
.set_map = vdpasim_set_map,
832+
.reset_map = vdpasim_reset_map,
799833
.bind_mm = vdpasim_bind_mm,
800834
.unbind_mm = vdpasim_unbind_mm,
801835
.free = vdpasim_free,

0 commit comments

Comments
 (0)