Message ID | 1588533678-23450-4-git-send-email-raphael.norwitz@nutanix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | vhost-user: Lift Max Ram Slots Limitation | expand |
Hi On Thu, May 21, 2020 at 7:00 AM Raphael Norwitz <raphael.norwitz@nutanix.com> wrote: > This change introduces a new feature to the vhost-user protocol allowing > a backend device to specify the maximum number of ram slots it supports. > > At this point, the value returned by the backend will be capped at the > maximum number of ram slots which can be supported by vhost-user, which > is currently set to 8 because of underlying protocol limitations. > > The returned value will be stored inside the VhostUserState struct so > that on device reconnect we can verify that the ram slot limitation > has not decreased since the last time the device connected. > > Signed-off-by: Raphael Norwitz <raphael.norwitz@nutanix.com> > Signed-off-by: Peter Turschmid <peter.turschm@nutanix.com> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- > docs/interop/vhost-user.rst | 16 ++++++++++++++ > hw/virtio/vhost-user.c | 49 > ++++++++++++++++++++++++++++++++++++++++-- > include/hw/virtio/vhost-user.h | 1 + > 3 files changed, 64 insertions(+), 2 deletions(-) > > diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst > index 3b1b660..b3cf5c3 100644 > --- a/docs/interop/vhost-user.rst > +++ b/docs/interop/vhost-user.rst > @@ -815,6 +815,7 @@ Protocol features > #define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12 > #define VHOST_USER_PROTOCOL_F_RESET_DEVICE 13 > #define VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS 14 > + #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS 15 > > Master message types > -------------------- > @@ -1263,6 +1264,21 @@ Master message types > > The state.num field is currently reserved and must be set to 0. > > +``VHOST_USER_GET_MAX_MEM_SLOTS`` > + :id: 36 > + :equivalent ioctl: N/A > + :slave payload: u64 > + > + When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol > + feature has been successfully negotiated, this message is submitted > + by master to the slave. The slave should return the message with a > + u64 payload containing the maximum number of memory slots for > + QEMU to expose to the guest. At this point, the value returned > + by the backend will be capped at the maximum number of ram slots > + which can be supported by vhost-user. Currently that limit is set > + at VHOST_USER_MAX_RAM_SLOTS = 8 because of underlying protocol > + limitations. > + > Slave message types > ------------------- > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c > index 442b0d6..0af593f 100644 > --- a/hw/virtio/vhost-user.c > +++ b/hw/virtio/vhost-user.c > @@ -59,6 +59,8 @@ enum VhostUserProtocolFeature { > VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, > VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, > VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, > + /* Feature 14 reserved for > VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS. */ > + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, > VHOST_USER_PROTOCOL_F_MAX > }; > > @@ -100,6 +102,8 @@ typedef enum VhostUserRequest { > VHOST_USER_SET_INFLIGHT_FD = 32, > VHOST_USER_GPU_SET_SOCKET = 33, > VHOST_USER_RESET_DEVICE = 34, > + /* Message number 35 reserved for VHOST_USER_VRING_KICK. */ > + VHOST_USER_GET_MAX_MEM_SLOTS = 36, > VHOST_USER_MAX > } VhostUserRequest; > > @@ -895,6 +899,23 @@ static int vhost_user_set_owner(struct vhost_dev *dev) > return 0; > } > > +static int vhost_user_get_max_memslots(struct vhost_dev *dev, > + uint64_t *max_memslots) > +{ > + uint64_t backend_max_memslots; > + int err; > + > + err = vhost_user_get_u64(dev, VHOST_USER_GET_MAX_MEM_SLOTS, > + &backend_max_memslots); > + if (err < 0) { > + return err; > + } > + > + *max_memslots = backend_max_memslots; > + > + return 0; > +} > + > static int vhost_user_reset_device(struct vhost_dev *dev) > { > VhostUserMsg msg = { > @@ -1392,7 +1413,7 @@ static int > vhost_user_postcopy_notifier(NotifierWithReturn *notifier, > > static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque) > { > - uint64_t features, protocol_features; > + uint64_t features, protocol_features, ram_slots; > struct vhost_user *u; > int err; > > @@ -1454,6 +1475,27 @@ static int vhost_user_backend_init(struct vhost_dev > *dev, void *opaque) > "slave-req protocol features."); > return -1; > } > + > + /* get max memory regions if backend supports configurable RAM > slots */ > + if (!virtio_has_feature(dev->protocol_features, > + > VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS)) { > + u->user->memory_slots = VHOST_MEMORY_MAX_NREGIONS; > + } else { > + err = vhost_user_get_max_memslots(dev, &ram_slots); > + if (err < 0) { > + return err; > + } > + > + if (ram_slots < u->user->memory_slots) { > + error_report("The backend specified a max ram slots limit > " > + "of %lu, when the prior validated limit was > %d. " > + "This limit should never decrease.", > ram_slots, > + u->user->memory_slots); > + return -1; > + } > + > + u->user->memory_slots = MIN(ram_slots, > VHOST_MEMORY_MAX_NREGIONS); > + } > } > > if (dev->migration_blocker == NULL && > @@ -1519,7 +1561,9 @@ static int vhost_user_get_vq_index(struct vhost_dev > *dev, int idx) > > static int vhost_user_memslots_limit(struct vhost_dev *dev) > { > - return VHOST_MEMORY_MAX_NREGIONS; > + struct vhost_user *u = dev->opaque; > + > + return u->user->memory_slots; > } > > static bool vhost_user_requires_shm_log(struct vhost_dev *dev) > @@ -1904,6 +1948,7 @@ bool vhost_user_init(VhostUserState *user, > CharBackend *chr, Error **errp) > return false; > } > user->chr = chr; > + user->memory_slots = 0; > return true; > } > > diff --git a/include/hw/virtio/vhost-user.h > b/include/hw/virtio/vhost-user.h > index 811e325..a9abca3 100644 > --- a/include/hw/virtio/vhost-user.h > +++ b/include/hw/virtio/vhost-user.h > @@ -20,6 +20,7 @@ typedef struct VhostUserHostNotifier { > typedef struct VhostUserState { > CharBackend *chr; > VhostUserHostNotifier notifier[VIRTIO_QUEUE_MAX]; > + int memory_slots; > } VhostUserState; > > bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error > **errp); > -- > 1.8.3.1 > >
diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst index 3b1b660..b3cf5c3 100644 --- a/docs/interop/vhost-user.rst +++ b/docs/interop/vhost-user.rst @@ -815,6 +815,7 @@ Protocol features #define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12 #define VHOST_USER_PROTOCOL_F_RESET_DEVICE 13 #define VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS 14 + #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS 15 Master message types -------------------- @@ -1263,6 +1264,21 @@ Master message types The state.num field is currently reserved and must be set to 0. +``VHOST_USER_GET_MAX_MEM_SLOTS`` + :id: 36 + :equivalent ioctl: N/A + :slave payload: u64 + + When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol + feature has been successfully negotiated, this message is submitted + by master to the slave. The slave should return the message with a + u64 payload containing the maximum number of memory slots for + QEMU to expose to the guest. At this point, the value returned + by the backend will be capped at the maximum number of ram slots + which can be supported by vhost-user. Currently that limit is set + at VHOST_USER_MAX_RAM_SLOTS = 8 because of underlying protocol + limitations. + Slave message types ------------------- diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 442b0d6..0af593f 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -59,6 +59,8 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, + /* Feature 14 reserved for VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS. */ + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, VHOST_USER_PROTOCOL_F_MAX }; @@ -100,6 +102,8 @@ typedef enum VhostUserRequest { VHOST_USER_SET_INFLIGHT_FD = 32, VHOST_USER_GPU_SET_SOCKET = 33, VHOST_USER_RESET_DEVICE = 34, + /* Message number 35 reserved for VHOST_USER_VRING_KICK. */ + VHOST_USER_GET_MAX_MEM_SLOTS = 36, VHOST_USER_MAX } VhostUserRequest; @@ -895,6 +899,23 @@ static int vhost_user_set_owner(struct vhost_dev *dev) return 0; } +static int vhost_user_get_max_memslots(struct vhost_dev *dev, + uint64_t *max_memslots) +{ + uint64_t backend_max_memslots; + int err; + + err = vhost_user_get_u64(dev, VHOST_USER_GET_MAX_MEM_SLOTS, + &backend_max_memslots); + if (err < 0) { + return err; + } + + *max_memslots = backend_max_memslots; + + return 0; +} + static int vhost_user_reset_device(struct vhost_dev *dev) { VhostUserMsg msg = { @@ -1392,7 +1413,7 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier, static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque) { - uint64_t features, protocol_features; + uint64_t features, protocol_features, ram_slots; struct vhost_user *u; int err; @@ -1454,6 +1475,27 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque) "slave-req protocol features."); return -1; } + + /* get max memory regions if backend supports configurable RAM slots */ + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS)) { + u->user->memory_slots = VHOST_MEMORY_MAX_NREGIONS; + } else { + err = vhost_user_get_max_memslots(dev, &ram_slots); + if (err < 0) { + return err; + } + + if (ram_slots < u->user->memory_slots) { + error_report("The backend specified a max ram slots limit " + "of %lu, when the prior validated limit was %d. " + "This limit should never decrease.", ram_slots, + u->user->memory_slots); + return -1; + } + + u->user->memory_slots = MIN(ram_slots, VHOST_MEMORY_MAX_NREGIONS); + } } if (dev->migration_blocker == NULL && @@ -1519,7 +1561,9 @@ static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx) static int vhost_user_memslots_limit(struct vhost_dev *dev) { - return VHOST_MEMORY_MAX_NREGIONS; + struct vhost_user *u = dev->opaque; + + return u->user->memory_slots; } static bool vhost_user_requires_shm_log(struct vhost_dev *dev) @@ -1904,6 +1948,7 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) return false; } user->chr = chr; + user->memory_slots = 0; return true; } diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index 811e325..a9abca3 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -20,6 +20,7 @@ typedef struct VhostUserHostNotifier { typedef struct VhostUserState { CharBackend *chr; VhostUserHostNotifier notifier[VIRTIO_QUEUE_MAX]; + int memory_slots; } VhostUserState; bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp);