Message ID | 1514865329-29258-4-git-send-email-changpeng.liu@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi On Tue, Jan 2, 2018 at 4:55 AM, Changpeng Liu <changpeng.liu@intel.com> wrote: > Enable VHOST_USER_GET_CONFIG/VHOST_USER_SET_CONFIG messages in > libvhost-user library, users can implement their own I/O target > based on the library. This enable the virtio config space delivered > between QEMU host device and the I/O target. > > Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> > --- > contrib/libvhost-user/libvhost-user.c | 54 +++++++++++++++++++++++++++++++++++ > contrib/libvhost-user/libvhost-user.h | 34 +++++++++++++++++++++- > 2 files changed, 87 insertions(+), 1 deletion(-) > > diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c > index f409bd3..9e12eb1 100644 > --- a/contrib/libvhost-user/libvhost-user.c > +++ b/contrib/libvhost-user/libvhost-user.c > @@ -84,6 +84,8 @@ vu_request_to_string(unsigned int req) > REQ(VHOST_USER_SET_SLAVE_REQ_FD), > REQ(VHOST_USER_IOTLB_MSG), > REQ(VHOST_USER_SET_VRING_ENDIAN), > + REQ(VHOST_USER_GET_CONFIG), > + REQ(VHOST_USER_SET_CONFIG), > REQ(VHOST_USER_MAX), > }; > #undef REQ > @@ -798,6 +800,53 @@ vu_set_slave_req_fd(VuDev *dev, VhostUserMsg *vmsg) > } > > static bool > +vu_get_config(VuDev *dev, VhostUserMsg *vmsg) > +{ > + int ret = -1; > + > + if (dev->iface->get_config) { > + ret = dev->iface->get_config(dev, vmsg->payload.config.region, > + vmsg->payload.config.size); > + } > + > + if (ret) { > + /* resize to zero to indicate an error to master */ > + vmsg->size = 0; > + } > + > + return true; > +} > + > +static bool > +vu_set_config(VuDev *dev, VhostUserMsg *vmsg) > +{ > + int ret = -1; > + bool reply_supported = !!(dev->protocol_features & > + (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)); > + None of the other messages in libvhost-user support the REPLY_ACK flag. Do you need it? If not, please drop it. If you need it, it's a better idea to make the reply explicit and mandatory in the protocol for SET_CONFIG. > + if (dev->iface->set_config) { > + ret = dev->iface->set_config(dev, vmsg->payload.config.region, > + vmsg->payload.config.offset, > + vmsg->payload.config.size, > + vmsg->payload.config.flags); > + } > + > + vmsg->size = sizeof(vmsg->payload.u64); > + if (!ret) { > + vmsg->payload.u64 = 0; > + } else { > + /* indicate an error in case reply supported */ > + vmsg->payload.u64 = 1; > + } > + > + if (reply_supported) { > + return true; > + } > + > + return false; > +} > + > +static bool > vu_process_message(VuDev *dev, VhostUserMsg *vmsg) > { > int do_reply = 0; > @@ -862,6 +911,10 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) > return vu_set_vring_enable_exec(dev, vmsg); > case VHOST_USER_SET_SLAVE_REQ_FD: > return vu_set_slave_req_fd(dev, vmsg); > + case VHOST_USER_GET_CONFIG: > + return vu_get_config(dev, vmsg); > + case VHOST_USER_SET_CONFIG: > + return vu_set_config(dev, vmsg); > case VHOST_USER_NONE: > break; > default: > @@ -970,6 +1023,7 @@ vu_init(VuDev *dev, > dev->iface = iface; > dev->log_call_fd = -1; > dev->slave_fd = -1; > + unrelated coding style change, please drop > for (i = 0; i < VHOST_MAX_NR_VIRTQUEUE; i++) { > dev->vq[i] = (VuVirtq) { > .call_fd = -1, .kick_fd = -1, .err_fd = -1, > diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h > index 2f5864b..b38959e 100644 > --- a/contrib/libvhost-user/libvhost-user.h > +++ b/contrib/libvhost-user/libvhost-user.h > @@ -30,6 +30,16 @@ > > #define VHOST_MEMORY_MAX_NREGIONS 8 > > +typedef enum VhostSetConfigType { > + VHOST_SET_CONFIG_TYPE_MASTER = 0, > + VHOST_SET_CONFIG_TYPE_MIGRATION = 1, > +} VhostSetConfigType; > + > +/* > + * Maximum size of virtio device config space > + */ > +#define VHOST_USER_MAX_CONFIG_SIZE 256 > + > enum VhostUserProtocolFeature { > VHOST_USER_PROTOCOL_F_MQ = 0, > VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, > @@ -38,7 +48,6 @@ enum VhostUserProtocolFeature { > VHOST_USER_PROTOCOL_F_NET_MTU = 4, > VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, > VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, > - unrelated coding style change, please drop > VHOST_USER_PROTOCOL_F_MAX > }; > > @@ -69,6 +78,8 @@ typedef enum VhostUserRequest { > VHOST_USER_SET_SLAVE_REQ_FD = 21, > VHOST_USER_IOTLB_MSG = 22, > VHOST_USER_SET_VRING_ENDIAN = 23, > + VHOST_USER_GET_CONFIG = 24, > + VHOST_USER_SET_CONFIG = 25, > VHOST_USER_MAX > } VhostUserRequest; > > @@ -90,6 +101,18 @@ typedef struct VhostUserLog { > uint64_t mmap_offset; > } VhostUserLog; > > +typedef struct VhostUserConfig { > + uint32_t offset; > + uint32_t size; > + uint32_t flags; > + uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; > +} VhostUserConfig; > + > +static VhostUserConfig c __attribute__ ((unused)); > +#define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \ > + + sizeof(c.size) \ > + + sizeof(c.flags)) > + > #if defined(_WIN32) > # define VU_PACKED __attribute__((gcc_struct, packed)) > #else > @@ -112,6 +135,7 @@ typedef struct VhostUserMsg { > struct vhost_vring_addr addr; > VhostUserMemory memory; > VhostUserLog log; > + VhostUserConfig config; > } payload; > > int fds[VHOST_MEMORY_MAX_NREGIONS]; > @@ -140,6 +164,10 @@ typedef int (*vu_process_msg_cb) (VuDev *dev, VhostUserMsg *vmsg, > int *do_reply); > typedef void (*vu_queue_set_started_cb) (VuDev *dev, int qidx, bool started); > typedef bool (*vu_queue_is_processed_in_order_cb) (VuDev *dev, int qidx); > +typedef int (*vu_get_config_cb) (VuDev *dev, uint8_t *config, uint32_t len); > +typedef int (*vu_set_config_cb) (VuDev *dev, const uint8_t *data, > + uint32_t offset, uint32_t size, > + uint32_t flags); > > typedef struct VuDevIface { > /* called by VHOST_USER_GET_FEATURES to get the features bitmask */ > @@ -162,6 +190,10 @@ typedef struct VuDevIface { > * on unmanaged exit/crash. > */ > vu_queue_is_processed_in_order_cb queue_is_processed_in_order; > + /* get the config space of the device */ > + vu_get_config_cb get_config; > + /* set the config space of the device */ > + vu_set_config_cb set_config; > } VuDevIface; > > typedef void (*vu_queue_handler_cb) (VuDev *dev, int qidx); > -- > 1.9.3 >
> -----Original Message----- > From: Marc-André Lureau [mailto:marcandre.lureau@gmail.com] > Sent: Tuesday, January 2, 2018 11:30 PM > To: Liu, Changpeng <changpeng.liu@intel.com> > Cc: QEMU <qemu-devel@nongnu.org>; Harris, James R <james.r.harris@intel.com>; > Michael S. Tsirkin <mst@redhat.com>; Stefan Hajnoczi <stefanha@gmail.com>; > Paolo Bonzini <pbonzini@redhat.com>; Felipe Franciosi <felipe@nutanix.com> > Subject: Re: [Qemu-devel] [PATCH v8 3/4] contrib/libvhost-user: enable virtio > config space messages > > Hi > > On Tue, Jan 2, 2018 at 4:55 AM, Changpeng Liu <changpeng.liu@intel.com> wrote: > > Enable VHOST_USER_GET_CONFIG/VHOST_USER_SET_CONFIG messages in > > libvhost-user library, users can implement their own I/O target > > based on the library. This enable the virtio config space delivered > > between QEMU host device and the I/O target. > > > > Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> > > --- > > contrib/libvhost-user/libvhost-user.c | 54 > +++++++++++++++++++++++++++++++++++ > > contrib/libvhost-user/libvhost-user.h | 34 +++++++++++++++++++++- > > 2 files changed, 87 insertions(+), 1 deletion(-) > > > > diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost- > user.c > > index f409bd3..9e12eb1 100644 > > --- a/contrib/libvhost-user/libvhost-user.c > > +++ b/contrib/libvhost-user/libvhost-user.c > > @@ -84,6 +84,8 @@ vu_request_to_string(unsigned int req) > > REQ(VHOST_USER_SET_SLAVE_REQ_FD), > > REQ(VHOST_USER_IOTLB_MSG), > > REQ(VHOST_USER_SET_VRING_ENDIAN), > > + REQ(VHOST_USER_GET_CONFIG), > > + REQ(VHOST_USER_SET_CONFIG), > > REQ(VHOST_USER_MAX), > > }; > > #undef REQ > > @@ -798,6 +800,53 @@ vu_set_slave_req_fd(VuDev *dev, VhostUserMsg *vmsg) > > } > > > > static bool > > +vu_get_config(VuDev *dev, VhostUserMsg *vmsg) > > +{ > > + int ret = -1; > > + > > + if (dev->iface->get_config) { > > + ret = dev->iface->get_config(dev, vmsg->payload.config.region, > > + vmsg->payload.config.size); > > + } > > + > > + if (ret) { > > + /* resize to zero to indicate an error to master */ > > + vmsg->size = 0; > > + } > > + > > + return true; > > +} > > + > > +static bool > > +vu_set_config(VuDev *dev, VhostUserMsg *vmsg) > > +{ > > + int ret = -1; > > + bool reply_supported = !!(dev->protocol_features & > > + (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)); > > + > > None of the other messages in libvhost-user support the REPLY_ACK > flag. Do you need it? If not, please drop it. Ok, will drop it. > > If you need it, it's a better idea to make the reply explicit and > mandatory in the protocol for SET_CONFIG. > > > + if (dev->iface->set_config) { > > + ret = dev->iface->set_config(dev, vmsg->payload.config.region, > > + vmsg->payload.config.offset, > > + vmsg->payload.config.size, > > + vmsg->payload.config.flags); > > + } > > + > > + vmsg->size = sizeof(vmsg->payload.u64); > > + if (!ret) { > > + vmsg->payload.u64 = 0; > > + } else { > > + /* indicate an error in case reply supported */ > > + vmsg->payload.u64 = 1; > > + } > > + > > + if (reply_supported) { > > + return true; > > + } > > + > > + return false; > > +} > > + > > +static bool > > vu_process_message(VuDev *dev, VhostUserMsg *vmsg) > > { > > int do_reply = 0; > > @@ -862,6 +911,10 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) > > return vu_set_vring_enable_exec(dev, vmsg); > > case VHOST_USER_SET_SLAVE_REQ_FD: > > return vu_set_slave_req_fd(dev, vmsg); > > + case VHOST_USER_GET_CONFIG: > > + return vu_get_config(dev, vmsg); > > + case VHOST_USER_SET_CONFIG: > > + return vu_set_config(dev, vmsg); > > case VHOST_USER_NONE: > > break; > > default: > > @@ -970,6 +1023,7 @@ vu_init(VuDev *dev, > > dev->iface = iface; > > dev->log_call_fd = -1; > > dev->slave_fd = -1; > > + > > unrelated coding style change, please drop Thanks. > > > for (i = 0; i < VHOST_MAX_NR_VIRTQUEUE; i++) { > > dev->vq[i] = (VuVirtq) { > > .call_fd = -1, .kick_fd = -1, .err_fd = -1, > > diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost- > user.h > > index 2f5864b..b38959e 100644 > > --- a/contrib/libvhost-user/libvhost-user.h > > +++ b/contrib/libvhost-user/libvhost-user.h > > @@ -30,6 +30,16 @@ > > > > #define VHOST_MEMORY_MAX_NREGIONS 8 > > > > +typedef enum VhostSetConfigType { > > + VHOST_SET_CONFIG_TYPE_MASTER = 0, > > + VHOST_SET_CONFIG_TYPE_MIGRATION = 1, > > +} VhostSetConfigType; > > + > > +/* > > + * Maximum size of virtio device config space > > + */ > > +#define VHOST_USER_MAX_CONFIG_SIZE 256 > > + > > enum VhostUserProtocolFeature { > > VHOST_USER_PROTOCOL_F_MQ = 0, > > VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, > > @@ -38,7 +48,6 @@ enum VhostUserProtocolFeature { > > VHOST_USER_PROTOCOL_F_NET_MTU = 4, > > VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, > > VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, > > - > > > unrelated coding style change, please drop Thanks. > > > VHOST_USER_PROTOCOL_F_MAX > > }; > > > > @@ -69,6 +78,8 @@ typedef enum VhostUserRequest { > > VHOST_USER_SET_SLAVE_REQ_FD = 21, > > VHOST_USER_IOTLB_MSG = 22, > > VHOST_USER_SET_VRING_ENDIAN = 23, > > + VHOST_USER_GET_CONFIG = 24, > > + VHOST_USER_SET_CONFIG = 25, > > VHOST_USER_MAX > > } VhostUserRequest; > > > > @@ -90,6 +101,18 @@ typedef struct VhostUserLog { > > uint64_t mmap_offset; > > } VhostUserLog; > > > > +typedef struct VhostUserConfig { > > + uint32_t offset; > > + uint32_t size; > > + uint32_t flags; > > + uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; > > +} VhostUserConfig; > > + > > +static VhostUserConfig c __attribute__ ((unused)); > > +#define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \ > > + + sizeof(c.size) \ > > + + sizeof(c.flags)) > > + > > #if defined(_WIN32) > > # define VU_PACKED __attribute__((gcc_struct, packed)) > > #else > > @@ -112,6 +135,7 @@ typedef struct VhostUserMsg { > > struct vhost_vring_addr addr; > > VhostUserMemory memory; > > VhostUserLog log; > > + VhostUserConfig config; > > } payload; > > > > int fds[VHOST_MEMORY_MAX_NREGIONS]; > > @@ -140,6 +164,10 @@ typedef int (*vu_process_msg_cb) (VuDev *dev, > VhostUserMsg *vmsg, > > int *do_reply); > > typedef void (*vu_queue_set_started_cb) (VuDev *dev, int qidx, bool started); > > typedef bool (*vu_queue_is_processed_in_order_cb) (VuDev *dev, int qidx); > > +typedef int (*vu_get_config_cb) (VuDev *dev, uint8_t *config, uint32_t len); > > +typedef int (*vu_set_config_cb) (VuDev *dev, const uint8_t *data, > > + uint32_t offset, uint32_t size, > > + uint32_t flags); > > > > typedef struct VuDevIface { > > /* called by VHOST_USER_GET_FEATURES to get the features bitmask */ > > @@ -162,6 +190,10 @@ typedef struct VuDevIface { > > * on unmanaged exit/crash. > > */ > > vu_queue_is_processed_in_order_cb queue_is_processed_in_order; > > + /* get the config space of the device */ > > + vu_get_config_cb get_config; > > + /* set the config space of the device */ > > + vu_set_config_cb set_config; > > } VuDevIface; > > > > typedef void (*vu_queue_handler_cb) (VuDev *dev, int qidx); > > -- > > 1.9.3 > > > > > -- > Marc-André Lureau
diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index f409bd3..9e12eb1 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -84,6 +84,8 @@ vu_request_to_string(unsigned int req) REQ(VHOST_USER_SET_SLAVE_REQ_FD), REQ(VHOST_USER_IOTLB_MSG), REQ(VHOST_USER_SET_VRING_ENDIAN), + REQ(VHOST_USER_GET_CONFIG), + REQ(VHOST_USER_SET_CONFIG), REQ(VHOST_USER_MAX), }; #undef REQ @@ -798,6 +800,53 @@ vu_set_slave_req_fd(VuDev *dev, VhostUserMsg *vmsg) } static bool +vu_get_config(VuDev *dev, VhostUserMsg *vmsg) +{ + int ret = -1; + + if (dev->iface->get_config) { + ret = dev->iface->get_config(dev, vmsg->payload.config.region, + vmsg->payload.config.size); + } + + if (ret) { + /* resize to zero to indicate an error to master */ + vmsg->size = 0; + } + + return true; +} + +static bool +vu_set_config(VuDev *dev, VhostUserMsg *vmsg) +{ + int ret = -1; + bool reply_supported = !!(dev->protocol_features & + (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)); + + if (dev->iface->set_config) { + ret = dev->iface->set_config(dev, vmsg->payload.config.region, + vmsg->payload.config.offset, + vmsg->payload.config.size, + vmsg->payload.config.flags); + } + + vmsg->size = sizeof(vmsg->payload.u64); + if (!ret) { + vmsg->payload.u64 = 0; + } else { + /* indicate an error in case reply supported */ + vmsg->payload.u64 = 1; + } + + if (reply_supported) { + return true; + } + + return false; +} + +static bool vu_process_message(VuDev *dev, VhostUserMsg *vmsg) { int do_reply = 0; @@ -862,6 +911,10 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) return vu_set_vring_enable_exec(dev, vmsg); case VHOST_USER_SET_SLAVE_REQ_FD: return vu_set_slave_req_fd(dev, vmsg); + case VHOST_USER_GET_CONFIG: + return vu_get_config(dev, vmsg); + case VHOST_USER_SET_CONFIG: + return vu_set_config(dev, vmsg); case VHOST_USER_NONE: break; default: @@ -970,6 +1023,7 @@ vu_init(VuDev *dev, dev->iface = iface; dev->log_call_fd = -1; dev->slave_fd = -1; + for (i = 0; i < VHOST_MAX_NR_VIRTQUEUE; i++) { dev->vq[i] = (VuVirtq) { .call_fd = -1, .kick_fd = -1, .err_fd = -1, diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index 2f5864b..b38959e 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -30,6 +30,16 @@ #define VHOST_MEMORY_MAX_NREGIONS 8 +typedef enum VhostSetConfigType { + VHOST_SET_CONFIG_TYPE_MASTER = 0, + VHOST_SET_CONFIG_TYPE_MIGRATION = 1, +} VhostSetConfigType; + +/* + * Maximum size of virtio device config space + */ +#define VHOST_USER_MAX_CONFIG_SIZE 256 + enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_MQ = 0, VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, @@ -38,7 +48,6 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_NET_MTU = 4, VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, - VHOST_USER_PROTOCOL_F_MAX }; @@ -69,6 +78,8 @@ typedef enum VhostUserRequest { VHOST_USER_SET_SLAVE_REQ_FD = 21, VHOST_USER_IOTLB_MSG = 22, VHOST_USER_SET_VRING_ENDIAN = 23, + VHOST_USER_GET_CONFIG = 24, + VHOST_USER_SET_CONFIG = 25, VHOST_USER_MAX } VhostUserRequest; @@ -90,6 +101,18 @@ typedef struct VhostUserLog { uint64_t mmap_offset; } VhostUserLog; +typedef struct VhostUserConfig { + uint32_t offset; + uint32_t size; + uint32_t flags; + uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; +} VhostUserConfig; + +static VhostUserConfig c __attribute__ ((unused)); +#define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \ + + sizeof(c.size) \ + + sizeof(c.flags)) + #if defined(_WIN32) # define VU_PACKED __attribute__((gcc_struct, packed)) #else @@ -112,6 +135,7 @@ typedef struct VhostUserMsg { struct vhost_vring_addr addr; VhostUserMemory memory; VhostUserLog log; + VhostUserConfig config; } payload; int fds[VHOST_MEMORY_MAX_NREGIONS]; @@ -140,6 +164,10 @@ typedef int (*vu_process_msg_cb) (VuDev *dev, VhostUserMsg *vmsg, int *do_reply); typedef void (*vu_queue_set_started_cb) (VuDev *dev, int qidx, bool started); typedef bool (*vu_queue_is_processed_in_order_cb) (VuDev *dev, int qidx); +typedef int (*vu_get_config_cb) (VuDev *dev, uint8_t *config, uint32_t len); +typedef int (*vu_set_config_cb) (VuDev *dev, const uint8_t *data, + uint32_t offset, uint32_t size, + uint32_t flags); typedef struct VuDevIface { /* called by VHOST_USER_GET_FEATURES to get the features bitmask */ @@ -162,6 +190,10 @@ typedef struct VuDevIface { * on unmanaged exit/crash. */ vu_queue_is_processed_in_order_cb queue_is_processed_in_order; + /* get the config space of the device */ + vu_get_config_cb get_config; + /* set the config space of the device */ + vu_set_config_cb set_config; } VuDevIface; typedef void (*vu_queue_handler_cb) (VuDev *dev, int qidx);
Enable VHOST_USER_GET_CONFIG/VHOST_USER_SET_CONFIG messages in libvhost-user library, users can implement their own I/O target based on the library. This enable the virtio config space delivered between QEMU host device and the I/O target. Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> --- contrib/libvhost-user/libvhost-user.c | 54 +++++++++++++++++++++++++++++++++++ contrib/libvhost-user/libvhost-user.h | 34 +++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-)