libvhost-user: support host notifier
This patch introduces the host notifier support in libvhost-user. A new API is added to support setting host notifier for each queue. Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
				
					committed by
					
						
						Michael S. Tsirkin
					
				
			
			
				
	
			
			
			
						parent
						
							44866521bd
						
					
				
				
					commit
					d84599f56c
				
			@@ -314,11 +314,6 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg)
 | 
				
			|||||||
        msg.msg_controllen = 0;
 | 
					        msg.msg_controllen = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Set the version in the flags when sending the reply */
 | 
					 | 
				
			||||||
    vmsg->flags &= ~VHOST_USER_VERSION_MASK;
 | 
					 | 
				
			||||||
    vmsg->flags |= VHOST_USER_VERSION;
 | 
					 | 
				
			||||||
    vmsg->flags |= VHOST_USER_REPLY_MASK;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        rc = sendmsg(conn_fd, &msg, 0);
 | 
					        rc = sendmsg(conn_fd, &msg, 0);
 | 
				
			||||||
    } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
 | 
					    } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
 | 
				
			||||||
@@ -341,6 +336,39 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg)
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					vu_send_reply(VuDev *dev, int conn_fd, VhostUserMsg *vmsg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Set the version in the flags when sending the reply */
 | 
				
			||||||
 | 
					    vmsg->flags &= ~VHOST_USER_VERSION_MASK;
 | 
				
			||||||
 | 
					    vmsg->flags |= VHOST_USER_VERSION;
 | 
				
			||||||
 | 
					    vmsg->flags |= VHOST_USER_REPLY_MASK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return vu_message_write(dev, conn_fd, vmsg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					vu_process_message_reply(VuDev *dev, const VhostUserMsg *vmsg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VhostUserMsg msg_reply;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((vmsg->flags & VHOST_USER_NEED_REPLY_MASK) == 0) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!vu_message_read(dev, dev->slave_fd, &msg_reply)) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (msg_reply.request != vmsg->request) {
 | 
				
			||||||
 | 
					        DPRINT("Received unexpected msg type. Expected %d received %d",
 | 
				
			||||||
 | 
					               vmsg->request, msg_reply.request);
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return msg_reply.payload.u64 == 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Kick the log_call_fd if required. */
 | 
					/* Kick the log_call_fd if required. */
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
vu_log_kick(VuDev *dev)
 | 
					vu_log_kick(VuDev *dev)
 | 
				
			||||||
@@ -536,7 +564,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* Send the message back to qemu with the addresses filled in */
 | 
					    /* Send the message back to qemu with the addresses filled in */
 | 
				
			||||||
    vmsg->fd_num = 0;
 | 
					    vmsg->fd_num = 0;
 | 
				
			||||||
    if (!vu_message_write(dev, dev->sock, vmsg)) {
 | 
					    if (!vu_send_reply(dev, dev->sock, vmsg)) {
 | 
				
			||||||
        vu_panic(dev, "failed to respond to set-mem-table for postcopy");
 | 
					        vu_panic(dev, "failed to respond to set-mem-table for postcopy");
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -916,6 +944,41 @@ void vu_set_queue_handler(VuDev *dev, VuVirtq *vq,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd,
 | 
				
			||||||
 | 
					                                int size, int offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int qidx = vq - dev->vq;
 | 
				
			||||||
 | 
					    int fd_num = 0;
 | 
				
			||||||
 | 
					    VhostUserMsg vmsg = {
 | 
				
			||||||
 | 
					        .request = VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG,
 | 
				
			||||||
 | 
					        .flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK,
 | 
				
			||||||
 | 
					        .size = sizeof(vmsg.payload.area),
 | 
				
			||||||
 | 
					        .payload.area = {
 | 
				
			||||||
 | 
					            .u64 = qidx & VHOST_USER_VRING_IDX_MASK,
 | 
				
			||||||
 | 
					            .size = size,
 | 
				
			||||||
 | 
					            .offset = offset,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (fd == -1) {
 | 
				
			||||||
 | 
					        vmsg.payload.area.u64 |= VHOST_USER_VRING_NOFD_MASK;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        vmsg.fds[fd_num++] = fd;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vmsg.fd_num = fd_num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((dev->protocol_features & VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) == 0) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!vu_message_write(dev, dev->slave_fd, &vmsg)) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return vu_process_message_reply(dev, &vmsg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vmsg)
 | 
					vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vmsg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -968,7 +1031,9 @@ static bool
 | 
				
			|||||||
vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg)
 | 
					vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint64_t features = 1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD |
 | 
					    uint64_t features = 1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD |
 | 
				
			||||||
                        1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ;
 | 
					                        1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ |
 | 
				
			||||||
 | 
					                        1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER |
 | 
				
			||||||
 | 
					                        1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (have_userfault()) {
 | 
					    if (have_userfault()) {
 | 
				
			||||||
        features |= 1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT;
 | 
					        features |= 1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT;
 | 
				
			||||||
@@ -1252,7 +1317,7 @@ vu_dispatch(VuDev *dev)
 | 
				
			|||||||
        goto end;
 | 
					        goto end;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!vu_message_write(dev, dev->sock, &vmsg)) {
 | 
					    if (!vu_send_reply(dev, dev->sock, &vmsg)) {
 | 
				
			||||||
        goto end;
 | 
					        goto end;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,8 @@ enum VhostUserProtocolFeature {
 | 
				
			|||||||
    VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
 | 
					    VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
 | 
				
			||||||
    VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
 | 
					    VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
 | 
				
			||||||
    VHOST_USER_PROTOCOL_F_CONFIG = 9,
 | 
					    VHOST_USER_PROTOCOL_F_CONFIG = 9,
 | 
				
			||||||
 | 
					    VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10,
 | 
				
			||||||
 | 
					    VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VHOST_USER_PROTOCOL_F_MAX
 | 
					    VHOST_USER_PROTOCOL_F_MAX
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -92,6 +94,14 @@ typedef enum VhostUserRequest {
 | 
				
			|||||||
    VHOST_USER_MAX
 | 
					    VHOST_USER_MAX
 | 
				
			||||||
} VhostUserRequest;
 | 
					} VhostUserRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum VhostUserSlaveRequest {
 | 
				
			||||||
 | 
					    VHOST_USER_SLAVE_NONE = 0,
 | 
				
			||||||
 | 
					    VHOST_USER_SLAVE_IOTLB_MSG = 1,
 | 
				
			||||||
 | 
					    VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2,
 | 
				
			||||||
 | 
					    VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG = 3,
 | 
				
			||||||
 | 
					    VHOST_USER_SLAVE_MAX
 | 
				
			||||||
 | 
					}  VhostUserSlaveRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct VhostUserMemoryRegion {
 | 
					typedef struct VhostUserMemoryRegion {
 | 
				
			||||||
    uint64_t guest_phys_addr;
 | 
					    uint64_t guest_phys_addr;
 | 
				
			||||||
    uint64_t memory_size;
 | 
					    uint64_t memory_size;
 | 
				
			||||||
@@ -122,6 +132,12 @@ static VhostUserConfig c __attribute__ ((unused));
 | 
				
			|||||||
                                   + sizeof(c.size) \
 | 
					                                   + sizeof(c.size) \
 | 
				
			||||||
                                   + sizeof(c.flags))
 | 
					                                   + sizeof(c.flags))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct VhostUserVringArea {
 | 
				
			||||||
 | 
					    uint64_t u64;
 | 
				
			||||||
 | 
					    uint64_t size;
 | 
				
			||||||
 | 
					    uint64_t offset;
 | 
				
			||||||
 | 
					} VhostUserVringArea;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(_WIN32)
 | 
					#if defined(_WIN32)
 | 
				
			||||||
# define VU_PACKED __attribute__((gcc_struct, packed))
 | 
					# define VU_PACKED __attribute__((gcc_struct, packed))
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
@@ -133,6 +149,7 @@ typedef struct VhostUserMsg {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define VHOST_USER_VERSION_MASK     (0x3)
 | 
					#define VHOST_USER_VERSION_MASK     (0x3)
 | 
				
			||||||
#define VHOST_USER_REPLY_MASK       (0x1 << 2)
 | 
					#define VHOST_USER_REPLY_MASK       (0x1 << 2)
 | 
				
			||||||
 | 
					#define VHOST_USER_NEED_REPLY_MASK  (0x1 << 3)
 | 
				
			||||||
    uint32_t flags;
 | 
					    uint32_t flags;
 | 
				
			||||||
    uint32_t size; /* the following payload size */
 | 
					    uint32_t size; /* the following payload size */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -145,6 +162,7 @@ typedef struct VhostUserMsg {
 | 
				
			|||||||
        VhostUserMemory memory;
 | 
					        VhostUserMemory memory;
 | 
				
			||||||
        VhostUserLog log;
 | 
					        VhostUserLog log;
 | 
				
			||||||
        VhostUserConfig config;
 | 
					        VhostUserConfig config;
 | 
				
			||||||
 | 
					        VhostUserVringArea area;
 | 
				
			||||||
    } payload;
 | 
					    } payload;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int fds[VHOST_MEMORY_MAX_NREGIONS];
 | 
					    int fds[VHOST_MEMORY_MAX_NREGIONS];
 | 
				
			||||||
@@ -368,6 +386,20 @@ VuVirtq *vu_get_queue(VuDev *dev, int qidx);
 | 
				
			|||||||
void vu_set_queue_handler(VuDev *dev, VuVirtq *vq,
 | 
					void vu_set_queue_handler(VuDev *dev, VuVirtq *vq,
 | 
				
			||||||
                          vu_queue_handler_cb handler);
 | 
					                          vu_queue_handler_cb handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * vu_set_queue_host_notifier:
 | 
				
			||||||
 | 
					 * @dev: a VuDev context
 | 
				
			||||||
 | 
					 * @vq: a VuVirtq queue
 | 
				
			||||||
 | 
					 * @fd: a file descriptor
 | 
				
			||||||
 | 
					 * @size: host page size
 | 
				
			||||||
 | 
					 * @offset: notifier offset in @fd file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Set queue's host notifier. This function may be called several
 | 
				
			||||||
 | 
					 * times for the same queue. If called with -1 @fd, the notifier
 | 
				
			||||||
 | 
					 * is removed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd,
 | 
				
			||||||
 | 
					                                int size, int offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * vu_queue_set_notification:
 | 
					 * vu_queue_set_notification:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user