hw/arm/xilinx_zynq: fix the capabilities register to match the datasheet
[qemu/ar7.git] / hw / virtio / vhost-user.c
blob6eb97980ad8a2cad5a11d938543c1789c2ba23f7
1 /*
2 * vhost-user
4 * Copyright (c) 2013 Virtual Open Systems Sarl.
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
9 */
11 #include "qemu/osdep.h"
12 #include "qapi/error.h"
13 #include "hw/virtio/vhost.h"
14 #include "hw/virtio/vhost-backend.h"
15 #include "hw/virtio/virtio-net.h"
16 #include "chardev/char-fe.h"
17 #include "sysemu/kvm.h"
18 #include "qemu/error-report.h"
19 #include "qemu/sockets.h"
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <linux/vhost.h>
26 #define VHOST_MEMORY_MAX_NREGIONS 8
27 #define VHOST_USER_F_PROTOCOL_FEATURES 30
30 * Maximum size of virtio device config space
32 #define VHOST_USER_MAX_CONFIG_SIZE 256
34 enum VhostUserProtocolFeature {
35 VHOST_USER_PROTOCOL_F_MQ = 0,
36 VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
37 VHOST_USER_PROTOCOL_F_RARP = 2,
38 VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
39 VHOST_USER_PROTOCOL_F_NET_MTU = 4,
40 VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
41 VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
43 VHOST_USER_PROTOCOL_F_MAX
46 #define VHOST_USER_PROTOCOL_FEATURE_MASK ((1 << VHOST_USER_PROTOCOL_F_MAX) - 1)
48 typedef enum VhostUserRequest {
49 VHOST_USER_NONE = 0,
50 VHOST_USER_GET_FEATURES = 1,
51 VHOST_USER_SET_FEATURES = 2,
52 VHOST_USER_SET_OWNER = 3,
53 VHOST_USER_RESET_OWNER = 4,
54 VHOST_USER_SET_MEM_TABLE = 5,
55 VHOST_USER_SET_LOG_BASE = 6,
56 VHOST_USER_SET_LOG_FD = 7,
57 VHOST_USER_SET_VRING_NUM = 8,
58 VHOST_USER_SET_VRING_ADDR = 9,
59 VHOST_USER_SET_VRING_BASE = 10,
60 VHOST_USER_GET_VRING_BASE = 11,
61 VHOST_USER_SET_VRING_KICK = 12,
62 VHOST_USER_SET_VRING_CALL = 13,
63 VHOST_USER_SET_VRING_ERR = 14,
64 VHOST_USER_GET_PROTOCOL_FEATURES = 15,
65 VHOST_USER_SET_PROTOCOL_FEATURES = 16,
66 VHOST_USER_GET_QUEUE_NUM = 17,
67 VHOST_USER_SET_VRING_ENABLE = 18,
68 VHOST_USER_SEND_RARP = 19,
69 VHOST_USER_NET_SET_MTU = 20,
70 VHOST_USER_SET_SLAVE_REQ_FD = 21,
71 VHOST_USER_IOTLB_MSG = 22,
72 VHOST_USER_SET_VRING_ENDIAN = 23,
73 VHOST_USER_GET_CONFIG = 24,
74 VHOST_USER_SET_CONFIG = 25,
75 VHOST_USER_MAX
76 } VhostUserRequest;
78 typedef enum VhostUserSlaveRequest {
79 VHOST_USER_SLAVE_NONE = 0,
80 VHOST_USER_SLAVE_IOTLB_MSG = 1,
81 VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2,
82 VHOST_USER_SLAVE_MAX
83 } VhostUserSlaveRequest;
85 typedef struct VhostUserMemoryRegion {
86 uint64_t guest_phys_addr;
87 uint64_t memory_size;
88 uint64_t userspace_addr;
89 uint64_t mmap_offset;
90 } VhostUserMemoryRegion;
92 typedef struct VhostUserMemory {
93 uint32_t nregions;
94 uint32_t padding;
95 VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
96 } VhostUserMemory;
98 typedef struct VhostUserLog {
99 uint64_t mmap_size;
100 uint64_t mmap_offset;
101 } VhostUserLog;
103 typedef struct VhostUserConfig {
104 uint32_t offset;
105 uint32_t size;
106 uint32_t flags;
107 uint8_t region[VHOST_USER_MAX_CONFIG_SIZE];
108 } VhostUserConfig;
110 static VhostUserConfig c __attribute__ ((unused));
111 #define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \
112 + sizeof(c.size) \
113 + sizeof(c.flags))
115 typedef struct {
116 VhostUserRequest request;
118 #define VHOST_USER_VERSION_MASK (0x3)
119 #define VHOST_USER_REPLY_MASK (0x1<<2)
120 #define VHOST_USER_NEED_REPLY_MASK (0x1 << 3)
121 uint32_t flags;
122 uint32_t size; /* the following payload size */
123 } QEMU_PACKED VhostUserHeader;
125 typedef union {
126 #define VHOST_USER_VRING_IDX_MASK (0xff)
127 #define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
128 uint64_t u64;
129 struct vhost_vring_state state;
130 struct vhost_vring_addr addr;
131 VhostUserMemory memory;
132 VhostUserLog log;
133 struct vhost_iotlb_msg iotlb;
134 VhostUserConfig config;
135 } VhostUserPayload;
137 typedef struct VhostUserMsg {
138 VhostUserHeader hdr;
139 VhostUserPayload payload;
140 } QEMU_PACKED VhostUserMsg;
142 static VhostUserMsg m __attribute__ ((unused));
143 #define VHOST_USER_HDR_SIZE (sizeof(VhostUserHeader))
145 #define VHOST_USER_PAYLOAD_SIZE (sizeof(VhostUserPayload))
147 /* The version of the protocol we support */
148 #define VHOST_USER_VERSION (0x1)
150 struct vhost_user {
151 CharBackend *chr;
152 int slave_fd;
155 static bool ioeventfd_enabled(void)
157 return kvm_enabled() && kvm_eventfds_enabled();
160 static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
162 struct vhost_user *u = dev->opaque;
163 CharBackend *chr = u->chr;
164 uint8_t *p = (uint8_t *) msg;
165 int r, size = VHOST_USER_HDR_SIZE;
167 r = qemu_chr_fe_read_all(chr, p, size);
168 if (r != size) {
169 error_report("Failed to read msg header. Read %d instead of %d."
170 " Original request %d.", r, size, msg->hdr.request);
171 goto fail;
174 /* validate received flags */
175 if (msg->hdr.flags != (VHOST_USER_REPLY_MASK | VHOST_USER_VERSION)) {
176 error_report("Failed to read msg header."
177 " Flags 0x%x instead of 0x%x.", msg->hdr.flags,
178 VHOST_USER_REPLY_MASK | VHOST_USER_VERSION);
179 goto fail;
182 /* validate message size is sane */
183 if (msg->hdr.size > VHOST_USER_PAYLOAD_SIZE) {
184 error_report("Failed to read msg header."
185 " Size %d exceeds the maximum %zu.", msg->hdr.size,
186 VHOST_USER_PAYLOAD_SIZE);
187 goto fail;
190 if (msg->hdr.size) {
191 p += VHOST_USER_HDR_SIZE;
192 size = msg->hdr.size;
193 r = qemu_chr_fe_read_all(chr, p, size);
194 if (r != size) {
195 error_report("Failed to read msg payload."
196 " Read %d instead of %d.", r, msg->hdr.size);
197 goto fail;
201 return 0;
203 fail:
204 return -1;
207 static int process_message_reply(struct vhost_dev *dev,
208 const VhostUserMsg *msg)
210 VhostUserMsg msg_reply;
212 if ((msg->hdr.flags & VHOST_USER_NEED_REPLY_MASK) == 0) {
213 return 0;
216 if (vhost_user_read(dev, &msg_reply) < 0) {
217 return -1;
220 if (msg_reply.hdr.request != msg->hdr.request) {
221 error_report("Received unexpected msg type."
222 "Expected %d received %d",
223 msg->hdr.request, msg_reply.hdr.request);
224 return -1;
227 return msg_reply.payload.u64 ? -1 : 0;
230 static bool vhost_user_one_time_request(VhostUserRequest request)
232 switch (request) {
233 case VHOST_USER_SET_OWNER:
234 case VHOST_USER_RESET_OWNER:
235 case VHOST_USER_SET_MEM_TABLE:
236 case VHOST_USER_GET_QUEUE_NUM:
237 case VHOST_USER_NET_SET_MTU:
238 return true;
239 default:
240 return false;
244 /* most non-init callers ignore the error */
245 static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
246 int *fds, int fd_num)
248 struct vhost_user *u = dev->opaque;
249 CharBackend *chr = u->chr;
250 int ret, size = VHOST_USER_HDR_SIZE + msg->hdr.size;
253 * For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE,
254 * we just need send it once in the first time. For later such
255 * request, we just ignore it.
257 if (vhost_user_one_time_request(msg->hdr.request) && dev->vq_index != 0) {
258 msg->hdr.flags &= ~VHOST_USER_NEED_REPLY_MASK;
259 return 0;
262 if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) {
263 error_report("Failed to set msg fds.");
264 return -1;
267 ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size);
268 if (ret != size) {
269 error_report("Failed to write msg."
270 " Wrote %d instead of %d.", ret, size);
271 return -1;
274 return 0;
277 static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
278 struct vhost_log *log)
280 int fds[VHOST_MEMORY_MAX_NREGIONS];
281 size_t fd_num = 0;
282 bool shmfd = virtio_has_feature(dev->protocol_features,
283 VHOST_USER_PROTOCOL_F_LOG_SHMFD);
284 VhostUserMsg msg = {
285 .hdr.request = VHOST_USER_SET_LOG_BASE,
286 .hdr.flags = VHOST_USER_VERSION,
287 .payload.log.mmap_size = log->size * sizeof(*(log->log)),
288 .payload.log.mmap_offset = 0,
289 .hdr.size = sizeof(msg.payload.log),
292 if (shmfd && log->fd != -1) {
293 fds[fd_num++] = log->fd;
296 if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
297 return -1;
300 if (shmfd) {
301 msg.hdr.size = 0;
302 if (vhost_user_read(dev, &msg) < 0) {
303 return -1;
306 if (msg.hdr.request != VHOST_USER_SET_LOG_BASE) {
307 error_report("Received unexpected msg type. "
308 "Expected %d received %d",
309 VHOST_USER_SET_LOG_BASE, msg.hdr.request);
310 return -1;
314 return 0;
317 static int vhost_user_set_mem_table(struct vhost_dev *dev,
318 struct vhost_memory *mem)
320 int fds[VHOST_MEMORY_MAX_NREGIONS];
321 int i, fd;
322 size_t fd_num = 0;
323 bool reply_supported = virtio_has_feature(dev->protocol_features,
324 VHOST_USER_PROTOCOL_F_REPLY_ACK);
326 VhostUserMsg msg = {
327 .hdr.request = VHOST_USER_SET_MEM_TABLE,
328 .hdr.flags = VHOST_USER_VERSION,
331 if (reply_supported) {
332 msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
335 for (i = 0; i < dev->mem->nregions; ++i) {
336 struct vhost_memory_region *reg = dev->mem->regions + i;
337 ram_addr_t offset;
338 MemoryRegion *mr;
340 assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
341 mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
342 &offset);
343 fd = memory_region_get_fd(mr);
344 if (fd > 0) {
345 if (fd_num == VHOST_MEMORY_MAX_NREGIONS) {
346 error_report("Failed preparing vhost-user memory table msg");
347 return -1;
349 msg.payload.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
350 msg.payload.memory.regions[fd_num].memory_size = reg->memory_size;
351 msg.payload.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
352 msg.payload.memory.regions[fd_num].mmap_offset = offset;
353 fds[fd_num++] = fd;
357 msg.payload.memory.nregions = fd_num;
359 if (!fd_num) {
360 error_report("Failed initializing vhost-user memory map, "
361 "consider using -object memory-backend-file share=on");
362 return -1;
365 msg.hdr.size = sizeof(msg.payload.memory.nregions);
366 msg.hdr.size += sizeof(msg.payload.memory.padding);
367 msg.hdr.size += fd_num * sizeof(VhostUserMemoryRegion);
369 if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
370 return -1;
373 if (reply_supported) {
374 return process_message_reply(dev, &msg);
377 return 0;
380 static int vhost_user_set_vring_addr(struct vhost_dev *dev,
381 struct vhost_vring_addr *addr)
383 VhostUserMsg msg = {
384 .hdr.request = VHOST_USER_SET_VRING_ADDR,
385 .hdr.flags = VHOST_USER_VERSION,
386 .payload.addr = *addr,
387 .hdr.size = sizeof(msg.payload.addr),
390 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
391 return -1;
394 return 0;
397 static int vhost_user_set_vring_endian(struct vhost_dev *dev,
398 struct vhost_vring_state *ring)
400 bool cross_endian = virtio_has_feature(dev->protocol_features,
401 VHOST_USER_PROTOCOL_F_CROSS_ENDIAN);
402 VhostUserMsg msg = {
403 .hdr.request = VHOST_USER_SET_VRING_ENDIAN,
404 .hdr.flags = VHOST_USER_VERSION,
405 .payload.state = *ring,
406 .hdr.size = sizeof(msg.payload.state),
409 if (!cross_endian) {
410 error_report("vhost-user trying to send unhandled ioctl");
411 return -1;
414 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
415 return -1;
418 return 0;
421 static int vhost_set_vring(struct vhost_dev *dev,
422 unsigned long int request,
423 struct vhost_vring_state *ring)
425 VhostUserMsg msg = {
426 .hdr.request = request,
427 .hdr.flags = VHOST_USER_VERSION,
428 .payload.state = *ring,
429 .hdr.size = sizeof(msg.payload.state),
432 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
433 return -1;
436 return 0;
439 static int vhost_user_set_vring_num(struct vhost_dev *dev,
440 struct vhost_vring_state *ring)
442 return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring);
445 static int vhost_user_set_vring_base(struct vhost_dev *dev,
446 struct vhost_vring_state *ring)
448 return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
451 static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
453 int i;
455 if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
456 return -1;
459 for (i = 0; i < dev->nvqs; ++i) {
460 struct vhost_vring_state state = {
461 .index = dev->vq_index + i,
462 .num = enable,
465 vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state);
468 return 0;
471 static int vhost_user_get_vring_base(struct vhost_dev *dev,
472 struct vhost_vring_state *ring)
474 VhostUserMsg msg = {
475 .hdr.request = VHOST_USER_GET_VRING_BASE,
476 .hdr.flags = VHOST_USER_VERSION,
477 .payload.state = *ring,
478 .hdr.size = sizeof(msg.payload.state),
481 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
482 return -1;
485 if (vhost_user_read(dev, &msg) < 0) {
486 return -1;
489 if (msg.hdr.request != VHOST_USER_GET_VRING_BASE) {
490 error_report("Received unexpected msg type. Expected %d received %d",
491 VHOST_USER_GET_VRING_BASE, msg.hdr.request);
492 return -1;
495 if (msg.hdr.size != sizeof(msg.payload.state)) {
496 error_report("Received bad msg size.");
497 return -1;
500 *ring = msg.payload.state;
502 return 0;
505 static int vhost_set_vring_file(struct vhost_dev *dev,
506 VhostUserRequest request,
507 struct vhost_vring_file *file)
509 int fds[VHOST_MEMORY_MAX_NREGIONS];
510 size_t fd_num = 0;
511 VhostUserMsg msg = {
512 .hdr.request = request,
513 .hdr.flags = VHOST_USER_VERSION,
514 .payload.u64 = file->index & VHOST_USER_VRING_IDX_MASK,
515 .hdr.size = sizeof(msg.payload.u64),
518 if (ioeventfd_enabled() && file->fd > 0) {
519 fds[fd_num++] = file->fd;
520 } else {
521 msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK;
524 if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
525 return -1;
528 return 0;
531 static int vhost_user_set_vring_kick(struct vhost_dev *dev,
532 struct vhost_vring_file *file)
534 return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
537 static int vhost_user_set_vring_call(struct vhost_dev *dev,
538 struct vhost_vring_file *file)
540 return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
543 static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64)
545 VhostUserMsg msg = {
546 .hdr.request = request,
547 .hdr.flags = VHOST_USER_VERSION,
548 .payload.u64 = u64,
549 .hdr.size = sizeof(msg.payload.u64),
552 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
553 return -1;
556 return 0;
559 static int vhost_user_set_features(struct vhost_dev *dev,
560 uint64_t features)
562 return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features);
565 static int vhost_user_set_protocol_features(struct vhost_dev *dev,
566 uint64_t features)
568 return vhost_user_set_u64(dev, VHOST_USER_SET_PROTOCOL_FEATURES, features);
571 static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
573 VhostUserMsg msg = {
574 .hdr.request = request,
575 .hdr.flags = VHOST_USER_VERSION,
578 if (vhost_user_one_time_request(request) && dev->vq_index != 0) {
579 return 0;
582 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
583 return -1;
586 if (vhost_user_read(dev, &msg) < 0) {
587 return -1;
590 if (msg.hdr.request != request) {
591 error_report("Received unexpected msg type. Expected %d received %d",
592 request, msg.hdr.request);
593 return -1;
596 if (msg.hdr.size != sizeof(msg.payload.u64)) {
597 error_report("Received bad msg size.");
598 return -1;
601 *u64 = msg.payload.u64;
603 return 0;
606 static int vhost_user_get_features(struct vhost_dev *dev, uint64_t *features)
608 return vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features);
611 static int vhost_user_set_owner(struct vhost_dev *dev)
613 VhostUserMsg msg = {
614 .hdr.request = VHOST_USER_SET_OWNER,
615 .hdr.flags = VHOST_USER_VERSION,
618 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
619 return -1;
622 return 0;
625 static int vhost_user_reset_device(struct vhost_dev *dev)
627 VhostUserMsg msg = {
628 .hdr.request = VHOST_USER_RESET_OWNER,
629 .hdr.flags = VHOST_USER_VERSION,
632 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
633 return -1;
636 return 0;
639 static int vhost_user_slave_handle_config_change(struct vhost_dev *dev)
641 int ret = -1;
643 if (!dev->config_ops) {
644 return -1;
647 if (dev->config_ops->vhost_dev_config_notifier) {
648 ret = dev->config_ops->vhost_dev_config_notifier(dev);
651 return ret;
654 static void slave_read(void *opaque)
656 struct vhost_dev *dev = opaque;
657 struct vhost_user *u = dev->opaque;
658 VhostUserHeader hdr = { 0, };
659 VhostUserPayload payload = { 0, };
660 int size, ret = 0;
662 /* Read header */
663 size = read(u->slave_fd, &hdr, VHOST_USER_HDR_SIZE);
664 if (size != VHOST_USER_HDR_SIZE) {
665 error_report("Failed to read from slave.");
666 goto err;
669 if (hdr.size > VHOST_USER_PAYLOAD_SIZE) {
670 error_report("Failed to read msg header."
671 " Size %d exceeds the maximum %zu.", hdr.size,
672 VHOST_USER_PAYLOAD_SIZE);
673 goto err;
676 /* Read payload */
677 size = read(u->slave_fd, &payload, hdr.size);
678 if (size != hdr.size) {
679 error_report("Failed to read payload from slave.");
680 goto err;
683 switch (hdr.request) {
684 case VHOST_USER_SLAVE_IOTLB_MSG:
685 ret = vhost_backend_handle_iotlb_msg(dev, &payload.iotlb);
686 break;
687 case VHOST_USER_SLAVE_CONFIG_CHANGE_MSG :
688 ret = vhost_user_slave_handle_config_change(dev);
689 break;
690 default:
691 error_report("Received unexpected msg type.");
692 ret = -EINVAL;
696 * REPLY_ACK feature handling. Other reply types has to be managed
697 * directly in their request handlers.
699 if (hdr.flags & VHOST_USER_NEED_REPLY_MASK) {
700 struct iovec iovec[2];
703 hdr.flags &= ~VHOST_USER_NEED_REPLY_MASK;
704 hdr.flags |= VHOST_USER_REPLY_MASK;
706 payload.u64 = !!ret;
707 hdr.size = sizeof(payload.u64);
709 iovec[0].iov_base = &hdr;
710 iovec[0].iov_len = VHOST_USER_HDR_SIZE;
711 iovec[1].iov_base = &payload;
712 iovec[1].iov_len = hdr.size;
714 size = writev(u->slave_fd, iovec, ARRAY_SIZE(iovec));
715 if (size != VHOST_USER_HDR_SIZE + hdr.size) {
716 error_report("Failed to send msg reply to slave.");
717 goto err;
721 return;
723 err:
724 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
725 close(u->slave_fd);
726 u->slave_fd = -1;
727 return;
730 static int vhost_setup_slave_channel(struct vhost_dev *dev)
732 VhostUserMsg msg = {
733 .hdr.request = VHOST_USER_SET_SLAVE_REQ_FD,
734 .hdr.flags = VHOST_USER_VERSION,
736 struct vhost_user *u = dev->opaque;
737 int sv[2], ret = 0;
738 bool reply_supported = virtio_has_feature(dev->protocol_features,
739 VHOST_USER_PROTOCOL_F_REPLY_ACK);
741 if (!virtio_has_feature(dev->protocol_features,
742 VHOST_USER_PROTOCOL_F_SLAVE_REQ)) {
743 return 0;
746 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
747 error_report("socketpair() failed");
748 return -1;
751 u->slave_fd = sv[0];
752 qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev);
754 if (reply_supported) {
755 msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
758 ret = vhost_user_write(dev, &msg, &sv[1], 1);
759 if (ret) {
760 goto out;
763 if (reply_supported) {
764 ret = process_message_reply(dev, &msg);
767 out:
768 close(sv[1]);
769 if (ret) {
770 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
771 close(u->slave_fd);
772 u->slave_fd = -1;
775 return ret;
778 static int vhost_user_init(struct vhost_dev *dev, void *opaque)
780 uint64_t features, protocol_features;
781 struct vhost_user *u;
782 int err;
784 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
786 u = g_new0(struct vhost_user, 1);
787 u->chr = opaque;
788 u->slave_fd = -1;
789 dev->opaque = u;
791 err = vhost_user_get_features(dev, &features);
792 if (err < 0) {
793 return err;
796 if (virtio_has_feature(features, VHOST_USER_F_PROTOCOL_FEATURES)) {
797 dev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
799 err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES,
800 &protocol_features);
801 if (err < 0) {
802 return err;
805 dev->protocol_features =
806 protocol_features & VHOST_USER_PROTOCOL_FEATURE_MASK;
807 err = vhost_user_set_protocol_features(dev, dev->protocol_features);
808 if (err < 0) {
809 return err;
812 /* query the max queues we support if backend supports Multiple Queue */
813 if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
814 err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
815 &dev->max_queues);
816 if (err < 0) {
817 return err;
821 if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) &&
822 !(virtio_has_feature(dev->protocol_features,
823 VHOST_USER_PROTOCOL_F_SLAVE_REQ) &&
824 virtio_has_feature(dev->protocol_features,
825 VHOST_USER_PROTOCOL_F_REPLY_ACK))) {
826 error_report("IOMMU support requires reply-ack and "
827 "slave-req protocol features.");
828 return -1;
832 if (dev->migration_blocker == NULL &&
833 !virtio_has_feature(dev->protocol_features,
834 VHOST_USER_PROTOCOL_F_LOG_SHMFD)) {
835 error_setg(&dev->migration_blocker,
836 "Migration disabled: vhost-user backend lacks "
837 "VHOST_USER_PROTOCOL_F_LOG_SHMFD feature.");
840 err = vhost_setup_slave_channel(dev);
841 if (err < 0) {
842 return err;
845 return 0;
848 static int vhost_user_cleanup(struct vhost_dev *dev)
850 struct vhost_user *u;
852 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
854 u = dev->opaque;
855 if (u->slave_fd >= 0) {
856 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
857 close(u->slave_fd);
858 u->slave_fd = -1;
860 g_free(u);
861 dev->opaque = 0;
863 return 0;
866 static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
868 assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
870 return idx;
873 static int vhost_user_memslots_limit(struct vhost_dev *dev)
875 return VHOST_MEMORY_MAX_NREGIONS;
878 static bool vhost_user_requires_shm_log(struct vhost_dev *dev)
880 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
882 return virtio_has_feature(dev->protocol_features,
883 VHOST_USER_PROTOCOL_F_LOG_SHMFD);
886 static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
888 VhostUserMsg msg = { 0 };
890 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
892 /* If guest supports GUEST_ANNOUNCE do nothing */
893 if (virtio_has_feature(dev->acked_features, VIRTIO_NET_F_GUEST_ANNOUNCE)) {
894 return 0;
897 /* if backend supports VHOST_USER_PROTOCOL_F_RARP ask it to send the RARP */
898 if (virtio_has_feature(dev->protocol_features,
899 VHOST_USER_PROTOCOL_F_RARP)) {
900 msg.hdr.request = VHOST_USER_SEND_RARP;
901 msg.hdr.flags = VHOST_USER_VERSION;
902 memcpy((char *)&msg.payload.u64, mac_addr, 6);
903 msg.hdr.size = sizeof(msg.payload.u64);
905 return vhost_user_write(dev, &msg, NULL, 0);
907 return -1;
910 static bool vhost_user_can_merge(struct vhost_dev *dev,
911 uint64_t start1, uint64_t size1,
912 uint64_t start2, uint64_t size2)
914 ram_addr_t offset;
915 int mfd, rfd;
916 MemoryRegion *mr;
918 mr = memory_region_from_host((void *)(uintptr_t)start1, &offset);
919 mfd = memory_region_get_fd(mr);
921 mr = memory_region_from_host((void *)(uintptr_t)start2, &offset);
922 rfd = memory_region_get_fd(mr);
924 return mfd == rfd;
927 static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu)
929 VhostUserMsg msg;
930 bool reply_supported = virtio_has_feature(dev->protocol_features,
931 VHOST_USER_PROTOCOL_F_REPLY_ACK);
933 if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU))) {
934 return 0;
937 msg.hdr.request = VHOST_USER_NET_SET_MTU;
938 msg.payload.u64 = mtu;
939 msg.hdr.size = sizeof(msg.payload.u64);
940 msg.hdr.flags = VHOST_USER_VERSION;
941 if (reply_supported) {
942 msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
945 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
946 return -1;
949 /* If reply_ack supported, slave has to ack specified MTU is valid */
950 if (reply_supported) {
951 return process_message_reply(dev, &msg);
954 return 0;
957 static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev,
958 struct vhost_iotlb_msg *imsg)
960 VhostUserMsg msg = {
961 .hdr.request = VHOST_USER_IOTLB_MSG,
962 .hdr.size = sizeof(msg.payload.iotlb),
963 .hdr.flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK,
964 .payload.iotlb = *imsg,
967 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
968 return -EFAULT;
971 return process_message_reply(dev, &msg);
975 static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled)
977 /* No-op as the receive channel is not dedicated to IOTLB messages. */
980 static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
981 uint32_t config_len)
983 VhostUserMsg msg = {
984 .hdr.request = VHOST_USER_GET_CONFIG,
985 .hdr.flags = VHOST_USER_VERSION,
986 .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + config_len,
989 if (config_len > VHOST_USER_MAX_CONFIG_SIZE) {
990 return -1;
993 msg.payload.config.offset = 0;
994 msg.payload.config.size = config_len;
995 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
996 return -1;
999 if (vhost_user_read(dev, &msg) < 0) {
1000 return -1;
1003 if (msg.hdr.request != VHOST_USER_GET_CONFIG) {
1004 error_report("Received unexpected msg type. Expected %d received %d",
1005 VHOST_USER_GET_CONFIG, msg.hdr.request);
1006 return -1;
1009 if (msg.hdr.size != VHOST_USER_CONFIG_HDR_SIZE + config_len) {
1010 error_report("Received bad msg size.");
1011 return -1;
1014 memcpy(config, msg.payload.config.region, config_len);
1016 return 0;
1019 static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data,
1020 uint32_t offset, uint32_t size, uint32_t flags)
1022 uint8_t *p;
1023 bool reply_supported = virtio_has_feature(dev->protocol_features,
1024 VHOST_USER_PROTOCOL_F_REPLY_ACK);
1026 VhostUserMsg msg = {
1027 .hdr.request = VHOST_USER_SET_CONFIG,
1028 .hdr.flags = VHOST_USER_VERSION,
1029 .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + size,
1032 if (reply_supported) {
1033 msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
1036 if (size > VHOST_USER_MAX_CONFIG_SIZE) {
1037 return -1;
1040 msg.payload.config.offset = offset,
1041 msg.payload.config.size = size,
1042 msg.payload.config.flags = flags,
1043 p = msg.payload.config.region;
1044 memcpy(p, data, size);
1046 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
1047 return -1;
1050 if (reply_supported) {
1051 return process_message_reply(dev, &msg);
1054 return 0;
1057 const VhostOps user_ops = {
1058 .backend_type = VHOST_BACKEND_TYPE_USER,
1059 .vhost_backend_init = vhost_user_init,
1060 .vhost_backend_cleanup = vhost_user_cleanup,
1061 .vhost_backend_memslots_limit = vhost_user_memslots_limit,
1062 .vhost_set_log_base = vhost_user_set_log_base,
1063 .vhost_set_mem_table = vhost_user_set_mem_table,
1064 .vhost_set_vring_addr = vhost_user_set_vring_addr,
1065 .vhost_set_vring_endian = vhost_user_set_vring_endian,
1066 .vhost_set_vring_num = vhost_user_set_vring_num,
1067 .vhost_set_vring_base = vhost_user_set_vring_base,
1068 .vhost_get_vring_base = vhost_user_get_vring_base,
1069 .vhost_set_vring_kick = vhost_user_set_vring_kick,
1070 .vhost_set_vring_call = vhost_user_set_vring_call,
1071 .vhost_set_features = vhost_user_set_features,
1072 .vhost_get_features = vhost_user_get_features,
1073 .vhost_set_owner = vhost_user_set_owner,
1074 .vhost_reset_device = vhost_user_reset_device,
1075 .vhost_get_vq_index = vhost_user_get_vq_index,
1076 .vhost_set_vring_enable = vhost_user_set_vring_enable,
1077 .vhost_requires_shm_log = vhost_user_requires_shm_log,
1078 .vhost_migration_done = vhost_user_migration_done,
1079 .vhost_backend_can_merge = vhost_user_can_merge,
1080 .vhost_net_set_mtu = vhost_user_net_set_mtu,
1081 .vhost_set_iotlb_callback = vhost_user_set_iotlb_callback,
1082 .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg,
1083 .vhost_get_config = vhost_user_get_config,
1084 .vhost_set_config = vhost_user_set_config,