qemu/hw/virtio/vhost-user.c
<<
>>
Prefs
   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 "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; /* the following payload 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/* The version of the protocol we support */
 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    /* validate received flags */
 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    /* validate message size is sane */
 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/* most non-init callers ignore the error */
 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     * For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE,
 229     * we just need send it once in the first time. For later such
 230     * request, we just ignore it.
 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    /* Read header */
 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    /* Read payload */
 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     * REPLY_ACK feature handling. Other reply types has to be managed
 653     * directly in their request handlers.
 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        /* query the max queues we support if backend supports Multiple Queue */
 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    /* If guest supports GUEST_ANNOUNCE do nothing */
 841    if (virtio_has_feature(dev->acked_features, VIRTIO_NET_F_GUEST_ANNOUNCE)) {
 842        return 0;
 843    }
 844
 845    /* if backend supports VHOST_USER_PROTOCOL_F_RARP ask it to send the RARP */
 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    /* If reply_ack supported, slave has to ack specified MTU is valid */
 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    /* No-op as the receive channel is not dedicated to IOTLB messages. */
 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