On Thu, Jan 18, 2024 at 4:32 AM Steven Sistare <steven.sistare@xxxxxxxxxx> wrote: > > On 1/10/2024 10:08 PM, Jason Wang wrote: > > On Thu, Jan 11, 2024 at 4:40 AM Steve Sistare <steven.sistare@xxxxxxxxxx> wrote: > >> > >> When device ownership is passed to a new process via VHOST_NEW_OWNER, > >> some devices need to know the new userland addresses of the dma mappings. > >> Define the new iotlb message type VHOST_IOTLB_REMAP to update the uaddr > >> of a mapping. The new uaddr must address the same memory object as > >> originally mapped. > >> > >> The user must suspend the device before the old address is invalidated, > >> and cannot resume it until after VHOST_IOTLB_REMAP is called, but this > >> requirement is not enforced by the API. > >> > >> Signed-off-by: Steve Sistare <steven.sistare@xxxxxxxxxx> > >> --- > >> drivers/vhost/vdpa.c | 34 ++++++++++++++++++++++++++++++++ > >> include/uapi/linux/vhost_types.h | 11 ++++++++++- > >> 2 files changed, 44 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c > >> index faed6471934a..ec5ca20bd47d 100644 > >> --- a/drivers/vhost/vdpa.c > >> +++ b/drivers/vhost/vdpa.c > >> @@ -1219,6 +1219,37 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v, > >> > >> } > >> > >> +static int vhost_vdpa_process_iotlb_remap(struct vhost_vdpa *v, > >> + struct vhost_iotlb *iotlb, > >> + struct vhost_iotlb_msg *msg) > >> +{ > >> + struct vdpa_device *vdpa = v->vdpa; > >> + const struct vdpa_config_ops *ops = vdpa->config; > >> + u32 asid = iotlb_to_asid(iotlb); > >> + u64 start = msg->iova; > >> + u64 last = start + msg->size - 1; > >> + struct vhost_iotlb_map *map; > >> + int r = 0; > >> + > >> + if (msg->perm || !msg->size) > >> + return -EINVAL; > >> + > >> + map = vhost_iotlb_itree_first(iotlb, start, last); > >> + if (!map) > >> + return -ENOENT; > >> + > >> + if (map->start != start || map->last != last) > >> + return -EINVAL; > >> + > >> + /* batch will finish with remap. non-batch must do it now. */ > >> + if (!v->in_batch) > >> + r = ops->set_map(vdpa, asid, iotlb); > >> + if (!r) > >> + map->addr = msg->uaddr; > > > > I may miss something, for example for PA mapping, > > > > 1) need to convert uaddr into phys addr > > 2) need to check whether the uaddr is backed by the same page or not? > > This code does not verify that the new size@uaddr points to the same physical > pages as the old size@uaddr. If the app screws up and they differ, then the app > may corrupt its own memory, but no-one else's. > > It would be expensive for large memories to verify page by page, O(npages), and such > verification lies on the critical path for virtual machine downtime during live update. > I could compare the properties of the vma(s) for the old size@uaddr vs the vma for the > new, but that is more complicated and would be a maintenance headache. When I submitted > such code to Alex W when writing the equivalent patches for vfio, he said don't check, > correctness is the user's responsibility. Ok, let's document this somewhere. Thanks > > - Steve > > >> + > >> + return r; > >> +} > >> + > >> static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v, > >> struct vhost_iotlb *iotlb, > >> struct vhost_iotlb_msg *msg) > >> @@ -1298,6 +1329,9 @@ static int vhost_vdpa_process_iotlb_msg(struct vhost_dev *dev, u32 asid, > >> ops->set_map(vdpa, asid, iotlb); > >> v->in_batch = false; > >> break; > >> + case VHOST_IOTLB_REMAP: > >> + r = vhost_vdpa_process_iotlb_remap(v, iotlb, msg); > >> + break; > >> default: > >> r = -EINVAL; > >> break; > >> diff --git a/include/uapi/linux/vhost_types.h b/include/uapi/linux/vhost_types.h > >> index 9177843951e9..35908315ff55 100644 > >> --- a/include/uapi/linux/vhost_types.h > >> +++ b/include/uapi/linux/vhost_types.h > >> @@ -79,7 +79,7 @@ struct vhost_iotlb_msg { > >> /* > >> * VHOST_IOTLB_BATCH_BEGIN and VHOST_IOTLB_BATCH_END allow modifying > >> * multiple mappings in one go: beginning with > >> - * VHOST_IOTLB_BATCH_BEGIN, followed by any number of > >> + * VHOST_IOTLB_BATCH_BEGIN, followed by any number of VHOST_IOTLB_REMAP or > >> * VHOST_IOTLB_UPDATE messages, and ending with VHOST_IOTLB_BATCH_END. > >> * When one of these two values is used as the message type, the rest > >> * of the fields in the message are ignored. There's no guarantee that > >> @@ -87,6 +87,15 @@ struct vhost_iotlb_msg { > >> */ > >> #define VHOST_IOTLB_BATCH_BEGIN 5 > >> #define VHOST_IOTLB_BATCH_END 6 > >> + > >> +/* > >> + * VHOST_IOTLB_REMAP registers a new uaddr for the existing mapping at iova. > >> + * The new uaddr must address the same memory object as originally mapped. > >> + * Failure to do so will result in user memory corruption and/or device > >> + * misbehavior. iova and size must match the arguments used to create the > >> + * an existing mapping. Protection is not changed, and perm must be 0. > >> + */ > >> +#define VHOST_IOTLB_REMAP 7 > >> __u8 type; > >> }; > >> > >> -- > >> 2.39.3 > >> > > >