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