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.
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>
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
{
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,
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,
83 } VhostUserSlaveRequest
;
85 typedef struct VhostUserMemoryRegion
{
86 uint64_t guest_phys_addr
;
88 uint64_t userspace_addr
;
90 } VhostUserMemoryRegion
;
92 typedef struct VhostUserMemory
{
95 VhostUserMemoryRegion regions
[VHOST_MEMORY_MAX_NREGIONS
];
98 typedef struct VhostUserLog
{
100 uint64_t mmap_offset
;
103 typedef struct VhostUserConfig
{
107 uint8_t region
[VHOST_USER_MAX_CONFIG_SIZE
];
110 static VhostUserConfig c
__attribute__ ((unused
));
111 #define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \
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)
122 uint32_t size
; /* the following payload size */
123 } QEMU_PACKED VhostUserHeader
;
126 #define VHOST_USER_VRING_IDX_MASK (0xff)
127 #define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
129 struct vhost_vring_state state
;
130 struct vhost_vring_addr addr
;
131 VhostUserMemory memory
;
133 struct vhost_iotlb_msg iotlb
;
134 VhostUserConfig config
;
137 typedef struct VhostUserMsg
{
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)
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
);
169 error_report("Failed to read msg header. Read %d instead of %d."
170 " Original request %d.", r
, size
, msg
->hdr
.request
);
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
);
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
);
191 p
+= VHOST_USER_HDR_SIZE
;
192 size
= msg
->hdr
.size
;
193 r
= qemu_chr_fe_read_all(chr
, p
, size
);
195 error_report("Failed to read msg payload."
196 " Read %d instead of %d.", r
, msg
->hdr
.size
);
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) {
216 if (vhost_user_read(dev
, &msg_reply
) < 0) {
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
);
227 return msg_reply
.payload
.u64
? -1 : 0;
230 static bool vhost_user_one_time_request(VhostUserRequest 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
:
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
;
262 if (qemu_chr_fe_set_msgfds(chr
, fds
, fd_num
) < 0) {
263 error_report("Failed to set msg fds.");
267 ret
= qemu_chr_fe_write_all(chr
, (const uint8_t *) msg
, size
);
269 error_report("Failed to write msg."
270 " Wrote %d instead of %d.", ret
, size
);
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
];
282 bool shmfd
= virtio_has_feature(dev
->protocol_features
,
283 VHOST_USER_PROTOCOL_F_LOG_SHMFD
);
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) {
302 if (vhost_user_read(dev
, &msg
) < 0) {
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
);
317 static int vhost_user_set_mem_table(struct vhost_dev
*dev
,
318 struct vhost_memory
*mem
)
320 int fds
[VHOST_MEMORY_MAX_NREGIONS
];
323 bool reply_supported
= virtio_has_feature(dev
->protocol_features
,
324 VHOST_USER_PROTOCOL_F_REPLY_ACK
);
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
;
340 assert((uintptr_t)reg
->userspace_addr
== reg
->userspace_addr
);
341 mr
= memory_region_from_host((void *)(uintptr_t)reg
->userspace_addr
,
343 fd
= memory_region_get_fd(mr
);
345 if (fd_num
== VHOST_MEMORY_MAX_NREGIONS
) {
346 error_report("Failed preparing vhost-user memory table msg");
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
;
357 msg
.payload
.memory
.nregions
= fd_num
;
360 error_report("Failed initializing vhost-user memory map, "
361 "consider using -object memory-backend-file share=on");
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) {
373 if (reply_supported
) {
374 return process_message_reply(dev
, &msg
);
380 static int vhost_user_set_vring_addr(struct vhost_dev
*dev
,
381 struct vhost_vring_addr
*addr
)
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) {
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
);
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
),
410 error_report("vhost-user trying to send unhandled ioctl");
414 if (vhost_user_write(dev
, &msg
, NULL
, 0) < 0) {
421 static int vhost_set_vring(struct vhost_dev
*dev
,
422 unsigned long int request
,
423 struct vhost_vring_state
*ring
)
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) {
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
)
455 if (!virtio_has_feature(dev
->features
, VHOST_USER_F_PROTOCOL_FEATURES
)) {
459 for (i
= 0; i
< dev
->nvqs
; ++i
) {
460 struct vhost_vring_state state
= {
461 .index
= dev
->vq_index
+ i
,
465 vhost_set_vring(dev
, VHOST_USER_SET_VRING_ENABLE
, &state
);
471 static int vhost_user_get_vring_base(struct vhost_dev
*dev
,
472 struct vhost_vring_state
*ring
)
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) {
485 if (vhost_user_read(dev
, &msg
) < 0) {
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
);
495 if (msg
.hdr
.size
!= sizeof(msg
.payload
.state
)) {
496 error_report("Received bad msg size.");
500 *ring
= msg
.payload
.state
;
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
];
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
;
521 msg
.payload
.u64
|= VHOST_USER_VRING_NOFD_MASK
;
524 if (vhost_user_write(dev
, &msg
, fds
, fd_num
) < 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
)
546 .hdr
.request
= request
,
547 .hdr
.flags
= VHOST_USER_VERSION
,
549 .hdr
.size
= sizeof(msg
.payload
.u64
),
552 if (vhost_user_write(dev
, &msg
, NULL
, 0) < 0) {
559 static int vhost_user_set_features(struct vhost_dev
*dev
,
562 return vhost_user_set_u64(dev
, VHOST_USER_SET_FEATURES
, features
);
565 static int vhost_user_set_protocol_features(struct vhost_dev
*dev
,
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
)
574 .hdr
.request
= request
,
575 .hdr
.flags
= VHOST_USER_VERSION
,
578 if (vhost_user_one_time_request(request
) && dev
->vq_index
!= 0) {
582 if (vhost_user_write(dev
, &msg
, NULL
, 0) < 0) {
586 if (vhost_user_read(dev
, &msg
) < 0) {
590 if (msg
.hdr
.request
!= request
) {
591 error_report("Received unexpected msg type. Expected %d received %d",
592 request
, msg
.hdr
.request
);
596 if (msg
.hdr
.size
!= sizeof(msg
.payload
.u64
)) {
597 error_report("Received bad msg size.");
601 *u64
= msg
.payload
.u64
;
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
)
614 .hdr
.request
= VHOST_USER_SET_OWNER
,
615 .hdr
.flags
= VHOST_USER_VERSION
,
618 if (vhost_user_write(dev
, &msg
, NULL
, 0) < 0) {
625 static int vhost_user_reset_device(struct vhost_dev
*dev
)
628 .hdr
.request
= VHOST_USER_RESET_OWNER
,
629 .hdr
.flags
= VHOST_USER_VERSION
,
632 if (vhost_user_write(dev
, &msg
, NULL
, 0) < 0) {
639 static int vhost_user_slave_handle_config_change(struct vhost_dev
*dev
)
643 if (!dev
->config_ops
) {
647 if (dev
->config_ops
->vhost_dev_config_notifier
) {
648 ret
= dev
->config_ops
->vhost_dev_config_notifier(dev
);
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, };
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.");
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
);
677 size
= read(u
->slave_fd
, &payload
, hdr
.size
);
678 if (size
!= hdr
.size
) {
679 error_report("Failed to read payload from slave.");
683 switch (hdr
.request
) {
684 case VHOST_USER_SLAVE_IOTLB_MSG
:
685 ret
= vhost_backend_handle_iotlb_msg(dev
, &payload
.iotlb
);
687 case VHOST_USER_SLAVE_CONFIG_CHANGE_MSG
:
688 ret
= vhost_user_slave_handle_config_change(dev
);
691 error_report("Received unexpected msg type.");
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
;
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.");
724 qemu_set_fd_handler(u
->slave_fd
, NULL
, NULL
, NULL
);
730 static int vhost_setup_slave_channel(struct vhost_dev
*dev
)
733 .hdr
.request
= VHOST_USER_SET_SLAVE_REQ_FD
,
734 .hdr
.flags
= VHOST_USER_VERSION
,
736 struct vhost_user
*u
= dev
->opaque
;
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
)) {
746 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, sv
) == -1) {
747 error_report("socketpair() failed");
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);
763 if (reply_supported
) {
764 ret
= process_message_reply(dev
, &msg
);
770 qemu_set_fd_handler(u
->slave_fd
, NULL
, NULL
, NULL
);
778 static int vhost_user_init(struct vhost_dev
*dev
, void *opaque
)
780 uint64_t features
, protocol_features
;
781 struct vhost_user
*u
;
784 assert(dev
->vhost_ops
->backend_type
== VHOST_BACKEND_TYPE_USER
);
786 u
= g_new0(struct vhost_user
, 1);
791 err
= vhost_user_get_features(dev
, &features
);
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
,
805 dev
->protocol_features
=
806 protocol_features
& VHOST_USER_PROTOCOL_FEATURE_MASK
;
807 err
= vhost_user_set_protocol_features(dev
, dev
->protocol_features
);
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
,
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.");
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
);
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
);
855 if (u
->slave_fd
>= 0) {
856 qemu_set_fd_handler(u
->slave_fd
, NULL
, NULL
, NULL
);
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
);
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
)) {
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);
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
)
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
);
927 static int vhost_user_net_set_mtu(struct vhost_dev
*dev
, uint16_t mtu
)
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
))) {
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) {
949 /* If reply_ack supported, slave has to ack specified MTU is valid */
950 if (reply_supported
) {
951 return process_message_reply(dev
, &msg
);
957 static int vhost_user_send_device_iotlb_msg(struct vhost_dev
*dev
,
958 struct vhost_iotlb_msg
*imsg
)
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) {
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
,
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
) {
993 msg
.payload
.config
.offset
= 0;
994 msg
.payload
.config
.size
= config_len
;
995 if (vhost_user_write(dev
, &msg
, NULL
, 0) < 0) {
999 if (vhost_user_read(dev
, &msg
) < 0) {
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
);
1009 if (msg
.hdr
.size
!= VHOST_USER_CONFIG_HDR_SIZE
+ config_len
) {
1010 error_report("Received bad msg size.");
1014 memcpy(config
, msg
.payload
.config
.region
, config_len
);
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
)
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
) {
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) {
1050 if (reply_supported
) {
1051 return process_message_reply(dev
, &msg
);
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
,