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