mirror of https://github.com/xemu-project/xemu.git
contrib/libvhost-user: enable virtio config space messages
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> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
00343e4b54
commit
0bc24d831e
|
@ -84,6 +84,8 @@ vu_request_to_string(unsigned int req)
|
||||||
REQ(VHOST_USER_SET_SLAVE_REQ_FD),
|
REQ(VHOST_USER_SET_SLAVE_REQ_FD),
|
||||||
REQ(VHOST_USER_IOTLB_MSG),
|
REQ(VHOST_USER_IOTLB_MSG),
|
||||||
REQ(VHOST_USER_SET_VRING_ENDIAN),
|
REQ(VHOST_USER_SET_VRING_ENDIAN),
|
||||||
|
REQ(VHOST_USER_GET_CONFIG),
|
||||||
|
REQ(VHOST_USER_SET_CONFIG),
|
||||||
REQ(VHOST_USER_MAX),
|
REQ(VHOST_USER_MAX),
|
||||||
};
|
};
|
||||||
#undef REQ
|
#undef REQ
|
||||||
|
@ -797,6 +799,42 @@ vu_set_slave_req_fd(VuDev *dev, VhostUserMsg *vmsg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (ret) {
|
||||||
|
vu_panic(dev, "Set virtio configuration space failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
|
vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
|
||||||
{
|
{
|
||||||
|
@ -862,6 +900,10 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
|
||||||
return vu_set_vring_enable_exec(dev, vmsg);
|
return vu_set_vring_enable_exec(dev, vmsg);
|
||||||
case VHOST_USER_SET_SLAVE_REQ_FD:
|
case VHOST_USER_SET_SLAVE_REQ_FD:
|
||||||
return vu_set_slave_req_fd(dev, vmsg);
|
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:
|
case VHOST_USER_NONE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -30,6 +30,16 @@
|
||||||
|
|
||||||
#define VHOST_MEMORY_MAX_NREGIONS 8
|
#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 {
|
enum VhostUserProtocolFeature {
|
||||||
VHOST_USER_PROTOCOL_F_MQ = 0,
|
VHOST_USER_PROTOCOL_F_MQ = 0,
|
||||||
VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
|
VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
|
||||||
|
@ -69,6 +79,8 @@ typedef enum VhostUserRequest {
|
||||||
VHOST_USER_SET_SLAVE_REQ_FD = 21,
|
VHOST_USER_SET_SLAVE_REQ_FD = 21,
|
||||||
VHOST_USER_IOTLB_MSG = 22,
|
VHOST_USER_IOTLB_MSG = 22,
|
||||||
VHOST_USER_SET_VRING_ENDIAN = 23,
|
VHOST_USER_SET_VRING_ENDIAN = 23,
|
||||||
|
VHOST_USER_GET_CONFIG = 24,
|
||||||
|
VHOST_USER_SET_CONFIG = 25,
|
||||||
VHOST_USER_MAX
|
VHOST_USER_MAX
|
||||||
} VhostUserRequest;
|
} VhostUserRequest;
|
||||||
|
|
||||||
|
@ -90,6 +102,18 @@ typedef struct VhostUserLog {
|
||||||
uint64_t mmap_offset;
|
uint64_t mmap_offset;
|
||||||
} VhostUserLog;
|
} 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)
|
#if defined(_WIN32)
|
||||||
# define VU_PACKED __attribute__((gcc_struct, packed))
|
# define VU_PACKED __attribute__((gcc_struct, packed))
|
||||||
#else
|
#else
|
||||||
|
@ -112,6 +136,7 @@ typedef struct VhostUserMsg {
|
||||||
struct vhost_vring_addr addr;
|
struct vhost_vring_addr addr;
|
||||||
VhostUserMemory memory;
|
VhostUserMemory memory;
|
||||||
VhostUserLog log;
|
VhostUserLog log;
|
||||||
|
VhostUserConfig config;
|
||||||
} payload;
|
} payload;
|
||||||
|
|
||||||
int fds[VHOST_MEMORY_MAX_NREGIONS];
|
int fds[VHOST_MEMORY_MAX_NREGIONS];
|
||||||
|
@ -140,6 +165,10 @@ typedef int (*vu_process_msg_cb) (VuDev *dev, VhostUserMsg *vmsg,
|
||||||
int *do_reply);
|
int *do_reply);
|
||||||
typedef void (*vu_queue_set_started_cb) (VuDev *dev, int qidx, bool started);
|
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 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 {
|
typedef struct VuDevIface {
|
||||||
/* called by VHOST_USER_GET_FEATURES to get the features bitmask */
|
/* called by VHOST_USER_GET_FEATURES to get the features bitmask */
|
||||||
|
@ -162,6 +191,10 @@ typedef struct VuDevIface {
|
||||||
* on unmanaged exit/crash.
|
* on unmanaged exit/crash.
|
||||||
*/
|
*/
|
||||||
vu_queue_is_processed_in_order_cb queue_is_processed_in_order;
|
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;
|
} VuDevIface;
|
||||||
|
|
||||||
typedef void (*vu_queue_handler_cb) (VuDev *dev, int qidx);
|
typedef void (*vu_queue_handler_cb) (VuDev *dev, int qidx);
|
||||||
|
|
Loading…
Reference in New Issue