1
2
3
4
5
6
7
8
9
10
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"
20
21#include <sys/ioctl.h>
22#include <sys/socket.h>
23#include <sys/un.h>
24#include <linux/vhost.h>
25
26#define VHOST_MEMORY_MAX_NREGIONS 8
27#define VHOST_USER_F_PROTOCOL_FEATURES 30
28
29enum VhostUserProtocolFeature {
30 VHOST_USER_PROTOCOL_F_MQ = 0,
31 VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
32 VHOST_USER_PROTOCOL_F_RARP = 2,
33 VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
34 VHOST_USER_PROTOCOL_F_NET_MTU = 4,
35 VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
36 VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
37
38 VHOST_USER_PROTOCOL_F_MAX
39};
40
41#define VHOST_USER_PROTOCOL_FEATURE_MASK ((1 << VHOST_USER_PROTOCOL_F_MAX) - 1)
42
43typedef enum VhostUserRequest {
44 VHOST_USER_NONE = 0,
45 VHOST_USER_GET_FEATURES = 1,
46 VHOST_USER_SET_FEATURES = 2,
47 VHOST_USER_SET_OWNER = 3,
48 VHOST_USER_RESET_OWNER = 4,
49 VHOST_USER_SET_MEM_TABLE = 5,
50 VHOST_USER_SET_LOG_BASE = 6,
51 VHOST_USER_SET_LOG_FD = 7,
52 VHOST_USER_SET_VRING_NUM = 8,
53 VHOST_USER_SET_VRING_ADDR = 9,
54 VHOST_USER_SET_VRING_BASE = 10,
55 VHOST_USER_GET_VRING_BASE = 11,
56 VHOST_USER_SET_VRING_KICK = 12,
57 VHOST_USER_SET_VRING_CALL = 13,
58 VHOST_USER_SET_VRING_ERR = 14,
59 VHOST_USER_GET_PROTOCOL_FEATURES = 15,
60 VHOST_USER_SET_PROTOCOL_FEATURES = 16,
61 VHOST_USER_GET_QUEUE_NUM = 17,
62 VHOST_USER_SET_VRING_ENABLE = 18,
63 VHOST_USER_SEND_RARP = 19,
64 VHOST_USER_NET_SET_MTU = 20,
65 VHOST_USER_SET_SLAVE_REQ_FD = 21,
66 VHOST_USER_IOTLB_MSG = 22,
67 VHOST_USER_SET_VRING_ENDIAN = 23,
68 VHOST_USER_MAX
69} VhostUserRequest;
70
71typedef enum VhostUserSlaveRequest {
72 VHOST_USER_SLAVE_NONE = 0,
73 VHOST_USER_SLAVE_IOTLB_MSG = 1,
74 VHOST_USER_SLAVE_MAX
75} VhostUserSlaveRequest;
76
77typedef struct VhostUserMemoryRegion {
78 uint64_t guest_phys_addr;
79 uint64_t memory_size;
80 uint64_t userspace_addr;
81 uint64_t mmap_offset;
82} VhostUserMemoryRegion;
83
84typedef struct VhostUserMemory {
85 uint32_t nregions;
86 uint32_t padding;
87 VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
88} VhostUserMemory;
89
90typedef struct VhostUserLog {
91 uint64_t mmap_size;
92 uint64_t mmap_offset;
93} VhostUserLog;
94
95typedef struct VhostUserMsg {
96 VhostUserRequest request;
97
98#define VHOST_USER_VERSION_MASK (0x3)
99#define VHOST_USER_REPLY_MASK (0x1<<2)
100#define VHOST_USER_NEED_REPLY_MASK (0x1 << 3)
101 uint32_t flags;
102 uint32_t size;
103 union {
104#define VHOST_USER_VRING_IDX_MASK (0xff)
105#define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
106 uint64_t u64;
107 struct vhost_vring_state state;
108 struct vhost_vring_addr addr;
109 VhostUserMemory memory;
110 VhostUserLog log;
111 struct vhost_iotlb_msg iotlb;
112 } payload;
113} QEMU_PACKED VhostUserMsg;
114
115static VhostUserMsg m __attribute__ ((unused));
116#define VHOST_USER_HDR_SIZE (sizeof(m.request) \
117 + sizeof(m.flags) \
118 + sizeof(m.size))
119
120#define VHOST_USER_PAYLOAD_SIZE (sizeof(m) - VHOST_USER_HDR_SIZE)
121
122
123#define VHOST_USER_VERSION (0x1)
124
125struct vhost_user {
126 CharBackend *chr;
127 int slave_fd;
128};
129
130static bool ioeventfd_enabled(void)
131{
132 return kvm_enabled() && kvm_eventfds_enabled();
133}
134
135static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
136{
137 struct vhost_user *u = dev->opaque;
138 CharBackend *chr = u->chr;
139 uint8_t *p = (uint8_t *) msg;
140 int r, size = VHOST_USER_HDR_SIZE;
141
142 r = qemu_chr_fe_read_all(chr, p, size);
143 if (r != size) {
144 error_report("Failed to read msg header. Read %d instead of %d."
145 " Original request %d.", r, size, msg->request);
146 goto fail;
147 }
148
149
150 if (msg->flags != (VHOST_USER_REPLY_MASK | VHOST_USER_VERSION)) {
151 error_report("Failed to read msg header."
152 " Flags 0x%x instead of 0x%x.", msg->flags,
153 VHOST_USER_REPLY_MASK | VHOST_USER_VERSION);
154 goto fail;
155 }
156
157
158 if (msg->size > VHOST_USER_PAYLOAD_SIZE) {
159 error_report("Failed to read msg header."
160 " Size %d exceeds the maximum %zu.", msg->size,
161 VHOST_USER_PAYLOAD_SIZE);
162 goto fail;
163 }
164
165 if (msg->size) {
166 p += VHOST_USER_HDR_SIZE;
167 size = msg->size;
168 r = qemu_chr_fe_read_all(chr, p, size);
169 if (r != size) {
170 error_report("Failed to read msg payload."
171 " Read %d instead of %d.", r, msg->size);
172 goto fail;
173 }
174 }
175
176 return 0;
177
178fail:
179 return -1;
180}
181
182static int process_message_reply(struct vhost_dev *dev,
183 const VhostUserMsg *msg)
184{
185 VhostUserMsg msg_reply;
186
187 if ((msg->flags & VHOST_USER_NEED_REPLY_MASK) == 0) {
188 return 0;
189 }
190
191 if (vhost_user_read(dev, &msg_reply) < 0) {
192 return -1;
193 }
194
195 if (msg_reply.request != msg->request) {
196 error_report("Received unexpected msg type."
197 "Expected %d received %d",
198 msg->request, msg_reply.request);
199 return -1;
200 }
201
202 return msg_reply.payload.u64 ? -1 : 0;
203}
204
205static bool vhost_user_one_time_request(VhostUserRequest request)
206{
207 switch (request) {
208 case VHOST_USER_SET_OWNER:
209 case VHOST_USER_RESET_OWNER:
210 case VHOST_USER_SET_MEM_TABLE:
211 case VHOST_USER_GET_QUEUE_NUM:
212 case VHOST_USER_NET_SET_MTU:
213 return true;
214 default:
215 return false;
216 }
217}
218
219
220static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
221 int *fds, int fd_num)
222{
223 struct vhost_user *u = dev->opaque;
224 CharBackend *chr = u->chr;
225 int ret, size = VHOST_USER_HDR_SIZE + msg->size;
226
227
228
229
230
231
232 if (vhost_user_one_time_request(msg->request) && dev->vq_index != 0) {
233 msg->flags &= ~VHOST_USER_NEED_REPLY_MASK;
234 return 0;
235 }
236
237 if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) {
238 error_report("Failed to set msg fds.");
239 return -1;
240 }
241
242 ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size);
243 if (ret != size) {
244 error_report("Failed to write msg."
245 " Wrote %d instead of %d.", ret, size);
246 return -1;
247 }
248
249 return 0;
250}
251
252static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
253 struct vhost_log *log)
254{
255 int fds[VHOST_MEMORY_MAX_NREGIONS];
256 size_t fd_num = 0;
257 bool shmfd = virtio_has_feature(dev->protocol_features,
258 VHOST_USER_PROTOCOL_F_LOG_SHMFD);
259 VhostUserMsg msg = {
260 .request = VHOST_USER_SET_LOG_BASE,
261 .flags = VHOST_USER_VERSION,
262 .payload.log.mmap_size = log->size * sizeof(*(log->log)),
263 .payload.log.mmap_offset = 0,
264 .size = sizeof(msg.payload.log),
265 };
266
267 if (shmfd && log->fd != -1) {
268 fds[fd_num++] = log->fd;
269 }
270
271 if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
272 return -1;
273 }
274
275 if (shmfd) {
276 msg.size = 0;
277 if (vhost_user_read(dev, &msg) < 0) {
278 return -1;
279 }
280
281 if (msg.request != VHOST_USER_SET_LOG_BASE) {
282 error_report("Received unexpected msg type. "
283 "Expected %d received %d",
284 VHOST_USER_SET_LOG_BASE, msg.request);
285 return -1;
286 }
287 }
288
289 return 0;
290}
291
292static int vhost_user_set_mem_table(struct vhost_dev *dev,
293 struct vhost_memory *mem)
294{
295 int fds[VHOST_MEMORY_MAX_NREGIONS];
296 int i, fd;
297 size_t fd_num = 0;
298 bool reply_supported = virtio_has_feature(dev->protocol_features,
299 VHOST_USER_PROTOCOL_F_REPLY_ACK);
300
301 VhostUserMsg msg = {
302 .request = VHOST_USER_SET_MEM_TABLE,
303 .flags = VHOST_USER_VERSION,
304 };
305
306 if (reply_supported) {
307 msg.flags |= VHOST_USER_NEED_REPLY_MASK;
308 }
309
310 for (i = 0; i < dev->mem->nregions; ++i) {
311 struct vhost_memory_region *reg = dev->mem->regions + i;
312 ram_addr_t offset;
313 MemoryRegion *mr;
314
315 assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
316 mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
317 &offset);
318 fd = memory_region_get_fd(mr);
319 if (fd > 0) {
320 if (fd_num == VHOST_MEMORY_MAX_NREGIONS) {
321 error_report("Failed preparing vhost-user memory table msg");
322 return -1;
323 }
324 msg.payload.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
325 msg.payload.memory.regions[fd_num].memory_size = reg->memory_size;
326 msg.payload.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
327 msg.payload.memory.regions[fd_num].mmap_offset = offset;
328 fds[fd_num++] = fd;
329 }
330 }
331
332 msg.payload.memory.nregions = fd_num;
333
334 if (!fd_num) {
335 error_report("Failed initializing vhost-user memory map, "
336 "consider using -object memory-backend-file share=on");
337 return -1;
338 }
339
340 msg.size = sizeof(msg.payload.memory.nregions);
341 msg.size += sizeof(msg.payload.memory.padding);
342 msg.size += fd_num * sizeof(VhostUserMemoryRegion);
343
344 if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
345 return -1;
346 }
347
348 if (reply_supported) {
349 return process_message_reply(dev, &msg);
350 }
351
352 return 0;
353}
354
355static int vhost_user_set_vring_addr(struct vhost_dev *dev,
356 struct vhost_vring_addr *addr)
357{
358 VhostUserMsg msg = {
359 .request = VHOST_USER_SET_VRING_ADDR,
360 .flags = VHOST_USER_VERSION,
361 .payload.addr = *addr,
362 .size = sizeof(msg.payload.addr),
363 };
364
365 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
366 return -1;
367 }
368
369 return 0;
370}
371
372static int vhost_user_set_vring_endian(struct vhost_dev *dev,
373 struct vhost_vring_state *ring)
374{
375 bool cross_endian = virtio_has_feature(dev->protocol_features,
376 VHOST_USER_PROTOCOL_F_CROSS_ENDIAN);
377 VhostUserMsg msg = {
378 .request = VHOST_USER_SET_VRING_ENDIAN,
379 .flags = VHOST_USER_VERSION,
380 .payload.state = *ring,
381 .size = sizeof(msg.payload.state),
382 };
383
384 if (!cross_endian) {
385 error_report("vhost-user trying to send unhandled ioctl");
386 return -1;
387 }
388
389 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
390 return -1;
391 }
392
393 return 0;
394}
395
396static int vhost_set_vring(struct vhost_dev *dev,
397 unsigned long int request,
398 struct vhost_vring_state *ring)
399{
400 VhostUserMsg msg = {
401 .request = request,
402 .flags = VHOST_USER_VERSION,
403 .payload.state = *ring,
404 .size = sizeof(msg.payload.state),
405 };
406
407 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
408 return -1;
409 }
410
411 return 0;
412}
413
414static int vhost_user_set_vring_num(struct vhost_dev *dev,
415 struct vhost_vring_state *ring)
416{
417 return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring);
418}
419
420static int vhost_user_set_vring_base(struct vhost_dev *dev,
421 struct vhost_vring_state *ring)
422{
423 return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
424}
425
426static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
427{
428 int i;
429
430 if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
431 return -1;
432 }
433
434 for (i = 0; i < dev->nvqs; ++i) {
435 struct vhost_vring_state state = {
436 .index = dev->vq_index + i,
437 .num = enable,
438 };
439
440 vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state);
441 }
442
443 return 0;
444}
445
446static int vhost_user_get_vring_base(struct vhost_dev *dev,
447 struct vhost_vring_state *ring)
448{
449 VhostUserMsg msg = {
450 .request = VHOST_USER_GET_VRING_BASE,
451 .flags = VHOST_USER_VERSION,
452 .payload.state = *ring,
453 .size = sizeof(msg.payload.state),
454 };
455
456 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
457 return -1;
458 }
459
460 if (vhost_user_read(dev, &msg) < 0) {
461 return -1;
462 }
463
464 if (msg.request != VHOST_USER_GET_VRING_BASE) {
465 error_report("Received unexpected msg type. Expected %d received %d",
466 VHOST_USER_GET_VRING_BASE, msg.request);
467 return -1;
468 }
469
470 if (msg.size != sizeof(msg.payload.state)) {
471 error_report("Received bad msg size.");
472 return -1;
473 }
474
475 *ring = msg.payload.state;
476
477 return 0;
478}
479
480static int vhost_set_vring_file(struct vhost_dev *dev,
481 VhostUserRequest request,
482 struct vhost_vring_file *file)
483{
484 int fds[VHOST_MEMORY_MAX_NREGIONS];
485 size_t fd_num = 0;
486 VhostUserMsg msg = {
487 .request = request,
488 .flags = VHOST_USER_VERSION,
489 .payload.u64 = file->index & VHOST_USER_VRING_IDX_MASK,
490 .size = sizeof(msg.payload.u64),
491 };
492
493 if (ioeventfd_enabled() && file->fd > 0) {
494 fds[fd_num++] = file->fd;
495 } else {
496 msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK;
497 }
498
499 if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
500 return -1;
501 }
502
503 return 0;
504}
505
506static int vhost_user_set_vring_kick(struct vhost_dev *dev,
507 struct vhost_vring_file *file)
508{
509 return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
510}
511
512static int vhost_user_set_vring_call(struct vhost_dev *dev,
513 struct vhost_vring_file *file)
514{
515 return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
516}
517
518static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64)
519{
520 VhostUserMsg msg = {
521 .request = request,
522 .flags = VHOST_USER_VERSION,
523 .payload.u64 = u64,
524 .size = sizeof(msg.payload.u64),
525 };
526
527 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
528 return -1;
529 }
530
531 return 0;
532}
533
534static int vhost_user_set_features(struct vhost_dev *dev,
535 uint64_t features)
536{
537 return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features);
538}
539
540static int vhost_user_set_protocol_features(struct vhost_dev *dev,
541 uint64_t features)
542{
543 return vhost_user_set_u64(dev, VHOST_USER_SET_PROTOCOL_FEATURES, features);
544}
545
546static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
547{
548 VhostUserMsg msg = {
549 .request = request,
550 .flags = VHOST_USER_VERSION,
551 };
552
553 if (vhost_user_one_time_request(request) && dev->vq_index != 0) {
554 return 0;
555 }
556
557 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
558 return -1;
559 }
560
561 if (vhost_user_read(dev, &msg) < 0) {
562 return -1;
563 }
564
565 if (msg.request != request) {
566 error_report("Received unexpected msg type. Expected %d received %d",
567 request, msg.request);
568 return -1;
569 }
570
571 if (msg.size != sizeof(msg.payload.u64)) {
572 error_report("Received bad msg size.");
573 return -1;
574 }
575
576 *u64 = msg.payload.u64;
577
578 return 0;
579}
580
581static int vhost_user_get_features(struct vhost_dev *dev, uint64_t *features)
582{
583 return vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features);
584}
585
586static int vhost_user_set_owner(struct vhost_dev *dev)
587{
588 VhostUserMsg msg = {
589 .request = VHOST_USER_SET_OWNER,
590 .flags = VHOST_USER_VERSION,
591 };
592
593 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
594 return -1;
595 }
596
597 return 0;
598}
599
600static int vhost_user_reset_device(struct vhost_dev *dev)
601{
602 VhostUserMsg msg = {
603 .request = VHOST_USER_RESET_OWNER,
604 .flags = VHOST_USER_VERSION,
605 };
606
607 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
608 return -1;
609 }
610
611 return 0;
612}
613
614static void slave_read(void *opaque)
615{
616 struct vhost_dev *dev = opaque;
617 struct vhost_user *u = dev->opaque;
618 VhostUserMsg msg = { 0, };
619 int size, ret = 0;
620
621
622 size = read(u->slave_fd, &msg, VHOST_USER_HDR_SIZE);
623 if (size != VHOST_USER_HDR_SIZE) {
624 error_report("Failed to read from slave.");
625 goto err;
626 }
627
628 if (msg.size > VHOST_USER_PAYLOAD_SIZE) {
629 error_report("Failed to read msg header."
630 " Size %d exceeds the maximum %zu.", msg.size,
631 VHOST_USER_PAYLOAD_SIZE);
632 goto err;
633 }
634
635
636 size = read(u->slave_fd, &msg.payload, msg.size);
637 if (size != msg.size) {
638 error_report("Failed to read payload from slave.");
639 goto err;
640 }
641
642 switch (msg.request) {
643 case VHOST_USER_SLAVE_IOTLB_MSG:
644 ret = vhost_backend_handle_iotlb_msg(dev, &msg.payload.iotlb);
645 break;
646 default:
647 error_report("Received unexpected msg type.");
648 ret = -EINVAL;
649 }
650
651
652
653
654
655 if (msg.flags & VHOST_USER_NEED_REPLY_MASK) {
656 msg.flags &= ~VHOST_USER_NEED_REPLY_MASK;
657 msg.flags |= VHOST_USER_REPLY_MASK;
658
659 msg.payload.u64 = !!ret;
660 msg.size = sizeof(msg.payload.u64);
661
662 size = write(u->slave_fd, &msg, VHOST_USER_HDR_SIZE + msg.size);
663 if (size != VHOST_USER_HDR_SIZE + msg.size) {
664 error_report("Failed to send msg reply to slave.");
665 goto err;
666 }
667 }
668
669 return;
670
671err:
672 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
673 close(u->slave_fd);
674 u->slave_fd = -1;
675 return;
676}
677
678static int vhost_setup_slave_channel(struct vhost_dev *dev)
679{
680 VhostUserMsg msg = {
681 .request = VHOST_USER_SET_SLAVE_REQ_FD,
682 .flags = VHOST_USER_VERSION,
683 };
684 struct vhost_user *u = dev->opaque;
685 int sv[2], ret = 0;
686 bool reply_supported = virtio_has_feature(dev->protocol_features,
687 VHOST_USER_PROTOCOL_F_REPLY_ACK);
688
689 if (!virtio_has_feature(dev->protocol_features,
690 VHOST_USER_PROTOCOL_F_SLAVE_REQ)) {
691 return 0;
692 }
693
694 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
695 error_report("socketpair() failed");
696 return -1;
697 }
698
699 u->slave_fd = sv[0];
700 qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev);
701
702 if (reply_supported) {
703 msg.flags |= VHOST_USER_NEED_REPLY_MASK;
704 }
705
706 ret = vhost_user_write(dev, &msg, &sv[1], 1);
707 if (ret) {
708 goto out;
709 }
710
711 if (reply_supported) {
712 ret = process_message_reply(dev, &msg);
713 }
714
715out:
716 close(sv[1]);
717 if (ret) {
718 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
719 close(u->slave_fd);
720 u->slave_fd = -1;
721 }
722
723 return ret;
724}
725
726static int vhost_user_init(struct vhost_dev *dev, void *opaque)
727{
728 uint64_t features, protocol_features;
729 struct vhost_user *u;
730 int err;
731
732 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
733
734 u = g_new0(struct vhost_user, 1);
735 u->chr = opaque;
736 u->slave_fd = -1;
737 dev->opaque = u;
738
739 err = vhost_user_get_features(dev, &features);
740 if (err < 0) {
741 return err;
742 }
743
744 if (virtio_has_feature(features, VHOST_USER_F_PROTOCOL_FEATURES)) {
745 dev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
746
747 err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES,
748 &protocol_features);
749 if (err < 0) {
750 return err;
751 }
752
753 dev->protocol_features =
754 protocol_features & VHOST_USER_PROTOCOL_FEATURE_MASK;
755 err = vhost_user_set_protocol_features(dev, dev->protocol_features);
756 if (err < 0) {
757 return err;
758 }
759
760
761 if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
762 err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
763 &dev->max_queues);
764 if (err < 0) {
765 return err;
766 }
767 }
768
769 if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) &&
770 !(virtio_has_feature(dev->protocol_features,
771 VHOST_USER_PROTOCOL_F_SLAVE_REQ) &&
772 virtio_has_feature(dev->protocol_features,
773 VHOST_USER_PROTOCOL_F_REPLY_ACK))) {
774 error_report("IOMMU support requires reply-ack and "
775 "slave-req protocol features.");
776 return -1;
777 }
778 }
779
780 if (dev->migration_blocker == NULL &&
781 !virtio_has_feature(dev->protocol_features,
782 VHOST_USER_PROTOCOL_F_LOG_SHMFD)) {
783 error_setg(&dev->migration_blocker,
784 "Migration disabled: vhost-user backend lacks "
785 "VHOST_USER_PROTOCOL_F_LOG_SHMFD feature.");
786 }
787
788 err = vhost_setup_slave_channel(dev);
789 if (err < 0) {
790 return err;
791 }
792
793 return 0;
794}
795
796static int vhost_user_cleanup(struct vhost_dev *dev)
797{
798 struct vhost_user *u;
799
800 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
801
802 u = dev->opaque;
803 if (u->slave_fd >= 0) {
804 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
805 close(u->slave_fd);
806 u->slave_fd = -1;
807 }
808 g_free(u);
809 dev->opaque = 0;
810
811 return 0;
812}
813
814static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
815{
816 assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
817
818 return idx;
819}
820
821static int vhost_user_memslots_limit(struct vhost_dev *dev)
822{
823 return VHOST_MEMORY_MAX_NREGIONS;
824}
825
826static bool vhost_user_requires_shm_log(struct vhost_dev *dev)
827{
828 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
829
830 return virtio_has_feature(dev->protocol_features,
831 VHOST_USER_PROTOCOL_F_LOG_SHMFD);
832}
833
834static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
835{
836 VhostUserMsg msg = { 0 };
837
838 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
839
840
841 if (virtio_has_feature(dev->acked_features, VIRTIO_NET_F_GUEST_ANNOUNCE)) {
842 return 0;
843 }
844
845
846 if (virtio_has_feature(dev->protocol_features,
847 VHOST_USER_PROTOCOL_F_RARP)) {
848 msg.request = VHOST_USER_SEND_RARP;
849 msg.flags = VHOST_USER_VERSION;
850 memcpy((char *)&msg.payload.u64, mac_addr, 6);
851 msg.size = sizeof(msg.payload.u64);
852
853 return vhost_user_write(dev, &msg, NULL, 0);
854 }
855 return -1;
856}
857
858static bool vhost_user_can_merge(struct vhost_dev *dev,
859 uint64_t start1, uint64_t size1,
860 uint64_t start2, uint64_t size2)
861{
862 ram_addr_t offset;
863 int mfd, rfd;
864 MemoryRegion *mr;
865
866 mr = memory_region_from_host((void *)(uintptr_t)start1, &offset);
867 mfd = memory_region_get_fd(mr);
868
869 mr = memory_region_from_host((void *)(uintptr_t)start2, &offset);
870 rfd = memory_region_get_fd(mr);
871
872 return mfd == rfd;
873}
874
875static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu)
876{
877 VhostUserMsg msg;
878 bool reply_supported = virtio_has_feature(dev->protocol_features,
879 VHOST_USER_PROTOCOL_F_REPLY_ACK);
880
881 if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU))) {
882 return 0;
883 }
884
885 msg.request = VHOST_USER_NET_SET_MTU;
886 msg.payload.u64 = mtu;
887 msg.size = sizeof(msg.payload.u64);
888 msg.flags = VHOST_USER_VERSION;
889 if (reply_supported) {
890 msg.flags |= VHOST_USER_NEED_REPLY_MASK;
891 }
892
893 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
894 return -1;
895 }
896
897
898 if (reply_supported) {
899 return process_message_reply(dev, &msg);
900 }
901
902 return 0;
903}
904
905static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev,
906 struct vhost_iotlb_msg *imsg)
907{
908 VhostUserMsg msg = {
909 .request = VHOST_USER_IOTLB_MSG,
910 .size = sizeof(msg.payload.iotlb),
911 .flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK,
912 .payload.iotlb = *imsg,
913 };
914
915 if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
916 return -EFAULT;
917 }
918
919 return process_message_reply(dev, &msg);
920}
921
922
923static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled)
924{
925
926}
927
928const VhostOps user_ops = {
929 .backend_type = VHOST_BACKEND_TYPE_USER,
930 .vhost_backend_init = vhost_user_init,
931 .vhost_backend_cleanup = vhost_user_cleanup,
932 .vhost_backend_memslots_limit = vhost_user_memslots_limit,
933 .vhost_set_log_base = vhost_user_set_log_base,
934 .vhost_set_mem_table = vhost_user_set_mem_table,
935 .vhost_set_vring_addr = vhost_user_set_vring_addr,
936 .vhost_set_vring_endian = vhost_user_set_vring_endian,
937 .vhost_set_vring_num = vhost_user_set_vring_num,
938 .vhost_set_vring_base = vhost_user_set_vring_base,
939 .vhost_get_vring_base = vhost_user_get_vring_base,
940 .vhost_set_vring_kick = vhost_user_set_vring_kick,
941 .vhost_set_vring_call = vhost_user_set_vring_call,
942 .vhost_set_features = vhost_user_set_features,
943 .vhost_get_features = vhost_user_get_features,
944 .vhost_set_owner = vhost_user_set_owner,
945 .vhost_reset_device = vhost_user_reset_device,
946 .vhost_get_vq_index = vhost_user_get_vq_index,
947 .vhost_set_vring_enable = vhost_user_set_vring_enable,
948 .vhost_requires_shm_log = vhost_user_requires_shm_log,
949 .vhost_migration_done = vhost_user_migration_done,
950 .vhost_backend_can_merge = vhost_user_can_merge,
951 .vhost_net_set_mtu = vhost_user_net_set_mtu,
952 .vhost_set_iotlb_callback = vhost_user_set_iotlb_callback,
953 .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg,
954};
955