qemu/hw/virtio/vhost-backend.c
<<
>>
Prefs
   1/*
   2 * vhost-backend
   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 "hw/virtio/vhost.h"
  13#include "hw/virtio/vhost-backend.h"
  14#include "qemu/error-report.h"
  15#include "linux/vhost.h"
  16
  17#include <sys/ioctl.h>
  18
  19static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
  20                             void *arg)
  21{
  22    int fd = (uintptr_t) dev->opaque;
  23
  24    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
  25
  26    return ioctl(fd, request, arg);
  27}
  28
  29static int vhost_kernel_init(struct vhost_dev *dev, void *opaque)
  30{
  31    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
  32
  33    dev->opaque = opaque;
  34
  35    return 0;
  36}
  37
  38static int vhost_kernel_cleanup(struct vhost_dev *dev)
  39{
  40    int fd = (uintptr_t) dev->opaque;
  41
  42    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
  43
  44    return close(fd);
  45}
  46
  47static int vhost_kernel_memslots_limit(struct vhost_dev *dev)
  48{
  49    int limit = 64;
  50    char *s;
  51
  52    if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions",
  53                            &s, NULL, NULL)) {
  54        uint64_t val = g_ascii_strtoull(s, NULL, 10);
  55        if (!((val == G_MAXUINT64 || !val) && errno)) {
  56            return val;
  57        }
  58        error_report("ignoring invalid max_mem_regions value in vhost module:"
  59                     " %s", s);
  60    }
  61    return limit;
  62}
  63
  64static int vhost_kernel_net_set_backend(struct vhost_dev *dev,
  65                                        struct vhost_vring_file *file)
  66{
  67    return vhost_kernel_call(dev, VHOST_NET_SET_BACKEND, file);
  68}
  69
  70static int vhost_kernel_scsi_set_endpoint(struct vhost_dev *dev,
  71                                          struct vhost_scsi_target *target)
  72{
  73    return vhost_kernel_call(dev, VHOST_SCSI_SET_ENDPOINT, target);
  74}
  75
  76static int vhost_kernel_scsi_clear_endpoint(struct vhost_dev *dev,
  77                                            struct vhost_scsi_target *target)
  78{
  79    return vhost_kernel_call(dev, VHOST_SCSI_CLEAR_ENDPOINT, target);
  80}
  81
  82static int vhost_kernel_scsi_get_abi_version(struct vhost_dev *dev, int *version)
  83{
  84    return vhost_kernel_call(dev, VHOST_SCSI_GET_ABI_VERSION, version);
  85}
  86
  87static int vhost_kernel_set_log_base(struct vhost_dev *dev, uint64_t base,
  88                                     struct vhost_log *log)
  89{
  90    return vhost_kernel_call(dev, VHOST_SET_LOG_BASE, &base);
  91}
  92
  93static int vhost_kernel_set_mem_table(struct vhost_dev *dev,
  94                                      struct vhost_memory *mem)
  95{
  96    return vhost_kernel_call(dev, VHOST_SET_MEM_TABLE, mem);
  97}
  98
  99static int vhost_kernel_set_vring_addr(struct vhost_dev *dev,
 100                                       struct vhost_vring_addr *addr)
 101{
 102    return vhost_kernel_call(dev, VHOST_SET_VRING_ADDR, addr);
 103}
 104
 105static int vhost_kernel_set_vring_endian(struct vhost_dev *dev,
 106                                         struct vhost_vring_state *ring)
 107{
 108    return vhost_kernel_call(dev, VHOST_SET_VRING_ENDIAN, ring);
 109}
 110
 111static int vhost_kernel_set_vring_num(struct vhost_dev *dev,
 112                                      struct vhost_vring_state *ring)
 113{
 114    return vhost_kernel_call(dev, VHOST_SET_VRING_NUM, ring);
 115}
 116
 117static int vhost_kernel_set_vring_base(struct vhost_dev *dev,
 118                                       struct vhost_vring_state *ring)
 119{
 120    return vhost_kernel_call(dev, VHOST_SET_VRING_BASE, ring);
 121}
 122
 123static int vhost_kernel_get_vring_base(struct vhost_dev *dev,
 124                                       struct vhost_vring_state *ring)
 125{
 126    return vhost_kernel_call(dev, VHOST_GET_VRING_BASE, ring);
 127}
 128
 129static int vhost_kernel_set_vring_kick(struct vhost_dev *dev,
 130                                       struct vhost_vring_file *file)
 131{
 132    return vhost_kernel_call(dev, VHOST_SET_VRING_KICK, file);
 133}
 134
 135static int vhost_kernel_set_vring_call(struct vhost_dev *dev,
 136                                       struct vhost_vring_file *file)
 137{
 138    return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
 139}
 140
 141static int vhost_kernel_set_features(struct vhost_dev *dev,
 142                                     uint64_t features)
 143{
 144    return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features);
 145}
 146
 147static int vhost_kernel_get_features(struct vhost_dev *dev,
 148                                     uint64_t *features)
 149{
 150    return vhost_kernel_call(dev, VHOST_GET_FEATURES, features);
 151}
 152
 153static int vhost_kernel_set_owner(struct vhost_dev *dev)
 154{
 155    return vhost_kernel_call(dev, VHOST_SET_OWNER, NULL);
 156}
 157
 158static int vhost_kernel_reset_device(struct vhost_dev *dev)
 159{
 160    return vhost_kernel_call(dev, VHOST_RESET_OWNER, NULL);
 161}
 162
 163static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx)
 164{
 165    assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
 166
 167    return idx - dev->vq_index;
 168}
 169
 170static const VhostOps kernel_ops = {
 171        .backend_type = VHOST_BACKEND_TYPE_KERNEL,
 172        .vhost_backend_init = vhost_kernel_init,
 173        .vhost_backend_cleanup = vhost_kernel_cleanup,
 174        .vhost_backend_memslots_limit = vhost_kernel_memslots_limit,
 175        .vhost_net_set_backend = vhost_kernel_net_set_backend,
 176        .vhost_scsi_set_endpoint = vhost_kernel_scsi_set_endpoint,
 177        .vhost_scsi_clear_endpoint = vhost_kernel_scsi_clear_endpoint,
 178        .vhost_scsi_get_abi_version = vhost_kernel_scsi_get_abi_version,
 179        .vhost_set_log_base = vhost_kernel_set_log_base,
 180        .vhost_set_mem_table = vhost_kernel_set_mem_table,
 181        .vhost_set_vring_addr = vhost_kernel_set_vring_addr,
 182        .vhost_set_vring_endian = vhost_kernel_set_vring_endian,
 183        .vhost_set_vring_num = vhost_kernel_set_vring_num,
 184        .vhost_set_vring_base = vhost_kernel_set_vring_base,
 185        .vhost_get_vring_base = vhost_kernel_get_vring_base,
 186        .vhost_set_vring_kick = vhost_kernel_set_vring_kick,
 187        .vhost_set_vring_call = vhost_kernel_set_vring_call,
 188        .vhost_set_features = vhost_kernel_set_features,
 189        .vhost_get_features = vhost_kernel_get_features,
 190        .vhost_set_owner = vhost_kernel_set_owner,
 191        .vhost_reset_device = vhost_kernel_reset_device,
 192        .vhost_get_vq_index = vhost_kernel_get_vq_index,
 193};
 194
 195int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
 196{
 197    int r = 0;
 198
 199    switch (backend_type) {
 200    case VHOST_BACKEND_TYPE_KERNEL:
 201        dev->vhost_ops = &kernel_ops;
 202        break;
 203    case VHOST_BACKEND_TYPE_USER:
 204        dev->vhost_ops = &user_ops;
 205        break;
 206    default:
 207        error_report("Unknown vhost backend type");
 208        r = -1;
 209    }
 210
 211    return r;
 212}
 213