提交 24d1eb33 编写于 作者: N Nikolay Nikolaev 提交者: Michael S. Tsirkin

Add vhost_ops to vhost_dev struct and replace all relevant ioctls

Decouple vhost from the Linux kernel by introducing vhost_ops. The
intention is to provide different backends - a 'kernel' backend based on
the ioctl interface, and an 'user' backend based on a UNIX domain socket
and shared memory interface.
Signed-off-by: NAntonios Motakis <a.motakis@virtualopensystems.com>
Signed-off-by: NNikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Reviewed-by: NMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
上级 81647a65
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <linux/kvm.h> #include <linux/kvm.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/virtio_ring.h> #include <linux/virtio_ring.h>
#include <netpacket/packet.h> #include <netpacket/packet.h>
#include <net/ethernet.h> #include <net/ethernet.h>
...@@ -177,7 +176,8 @@ static int vhost_net_start_one(struct vhost_net *net, ...@@ -177,7 +176,8 @@ static int vhost_net_start_one(struct vhost_net *net,
qemu_set_fd_handler(net->backend, NULL, NULL, NULL); qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
file.fd = net->backend; file.fd = net->backend;
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); const VhostOps *vhost_ops = net->dev.vhost_ops;
r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file);
if (r < 0) { if (r < 0) {
r = -errno; r = -errno;
goto fail; goto fail;
...@@ -187,7 +187,8 @@ static int vhost_net_start_one(struct vhost_net *net, ...@@ -187,7 +187,8 @@ static int vhost_net_start_one(struct vhost_net *net,
fail: fail:
file.fd = -1; file.fd = -1;
while (file.index-- > 0) { while (file.index-- > 0) {
int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file);
assert(r >= 0); assert(r >= 0);
} }
if (net->nc->info->poll) { if (net->nc->info->poll) {
...@@ -210,7 +211,8 @@ static void vhost_net_stop_one(struct vhost_net *net, ...@@ -210,7 +211,8 @@ static void vhost_net_stop_one(struct vhost_net *net,
} }
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file);
assert(r >= 0); assert(r >= 0);
} }
if (net->nc->info->poll) { if (net->nc->info->poll) {
......
...@@ -36,12 +36,13 @@ static const int kernel_feature_bits[] = { ...@@ -36,12 +36,13 @@ static const int kernel_feature_bits[] = {
static int vhost_scsi_set_endpoint(VHostSCSI *s) static int vhost_scsi_set_endpoint(VHostSCSI *s)
{ {
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
const VhostOps *vhost_ops = s->dev.vhost_ops;
struct vhost_scsi_target backend; struct vhost_scsi_target backend;
int ret; int ret;
memset(&backend, 0, sizeof(backend)); memset(&backend, 0, sizeof(backend));
pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn); pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
ret = ioctl(s->dev.control, VHOST_SCSI_SET_ENDPOINT, &backend); ret = vhost_ops->vhost_call(&s->dev, VHOST_SCSI_SET_ENDPOINT, &backend);
if (ret < 0) { if (ret < 0) {
return -errno; return -errno;
} }
...@@ -52,10 +53,11 @@ static void vhost_scsi_clear_endpoint(VHostSCSI *s) ...@@ -52,10 +53,11 @@ static void vhost_scsi_clear_endpoint(VHostSCSI *s)
{ {
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
struct vhost_scsi_target backend; struct vhost_scsi_target backend;
const VhostOps *vhost_ops = s->dev.vhost_ops;
memset(&backend, 0, sizeof(backend)); memset(&backend, 0, sizeof(backend));
pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn); pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
ioctl(s->dev.control, VHOST_SCSI_CLEAR_ENDPOINT, &backend); vhost_ops->vhost_call(&s->dev, VHOST_SCSI_CLEAR_ENDPOINT, &backend);
} }
static int vhost_scsi_start(VHostSCSI *s) static int vhost_scsi_start(VHostSCSI *s)
...@@ -64,13 +66,15 @@ static int vhost_scsi_start(VHostSCSI *s) ...@@ -64,13 +66,15 @@ static int vhost_scsi_start(VHostSCSI *s)
VirtIODevice *vdev = VIRTIO_DEVICE(s); VirtIODevice *vdev = VIRTIO_DEVICE(s);
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
const VhostOps *vhost_ops = s->dev.vhost_ops;
if (!k->set_guest_notifiers) { if (!k->set_guest_notifiers) {
error_report("binding does not support guest notifiers"); error_report("binding does not support guest notifiers");
return -ENOSYS; return -ENOSYS;
} }
ret = ioctl(s->dev.control, VHOST_SCSI_GET_ABI_VERSION, &abi_version); ret = vhost_ops->vhost_call(&s->dev,
VHOST_SCSI_GET_ABI_VERSION, &abi_version);
if (ret < 0) { if (ret < 0) {
return -errno; return -errno;
} }
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* GNU GPL, version 2 or (at your option) any later version. * GNU GPL, version 2 or (at your option) any later version.
*/ */
#include <sys/ioctl.h>
#include "hw/virtio/vhost.h" #include "hw/virtio/vhost.h"
#include "hw/hw.h" #include "hw/hw.h"
#include "qemu/atomic.h" #include "qemu/atomic.h"
...@@ -289,7 +288,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size) ...@@ -289,7 +288,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
log = g_malloc0(size * sizeof *log); log = g_malloc0(size * sizeof *log);
log_base = (uint64_t)(unsigned long)log; log_base = (uint64_t)(unsigned long)log;
r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base);
assert(r >= 0); assert(r >= 0);
/* Sync only the range covered by the old log */ /* Sync only the range covered by the old log */
if (dev->log_size) { if (dev->log_size) {
...@@ -456,7 +455,7 @@ static void vhost_commit(MemoryListener *listener) ...@@ -456,7 +455,7 @@ static void vhost_commit(MemoryListener *listener)
} }
if (!dev->log_enabled) { if (!dev->log_enabled) {
r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->mem);
assert(r >= 0); assert(r >= 0);
dev->memory_changed = false; dev->memory_changed = false;
return; return;
...@@ -469,7 +468,7 @@ static void vhost_commit(MemoryListener *listener) ...@@ -469,7 +468,7 @@ static void vhost_commit(MemoryListener *listener)
if (dev->log_size < log_size) { if (dev->log_size < log_size) {
vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER); vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER);
} }
r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->mem);
assert(r >= 0); assert(r >= 0);
/* To log less, can only decrease log size after table update. */ /* To log less, can only decrease log size after table update. */
if (dev->log_size > log_size + VHOST_LOG_BUFFER) { if (dev->log_size > log_size + VHOST_LOG_BUFFER) {
...@@ -537,7 +536,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, ...@@ -537,7 +536,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
.log_guest_addr = vq->used_phys, .log_guest_addr = vq->used_phys,
.flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0, .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
}; };
int r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr); int r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ADDR, &addr);
if (r < 0) { if (r < 0) {
return -errno; return -errno;
} }
...@@ -551,7 +550,7 @@ static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log) ...@@ -551,7 +550,7 @@ static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log)
if (enable_log) { if (enable_log) {
features |= 0x1 << VHOST_F_LOG_ALL; features |= 0x1 << VHOST_F_LOG_ALL;
} }
r = ioctl(dev->control, VHOST_SET_FEATURES, &features); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_FEATURES, &features);
return r < 0 ? -errno : 0; return r < 0 ? -errno : 0;
} }
...@@ -664,13 +663,13 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, ...@@ -664,13 +663,13 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs); assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
vq->num = state.num = virtio_queue_get_num(vdev, idx); vq->num = state.num = virtio_queue_get_num(vdev, idx);
r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_NUM, &state);
if (r) { if (r) {
return -errno; return -errno;
} }
state.num = virtio_queue_get_last_avail_idx(vdev, idx); state.num = virtio_queue_get_last_avail_idx(vdev, idx);
r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_BASE, &state);
if (r) { if (r) {
return -errno; return -errno;
} }
...@@ -712,7 +711,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, ...@@ -712,7 +711,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
} }
file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq)); file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_KICK, &file);
if (r) { if (r) {
r = -errno; r = -errno;
goto fail_kick; goto fail_kick;
...@@ -750,7 +749,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, ...@@ -750,7 +749,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
}; };
int r; int r;
assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs); assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state); r = dev->vhost_ops->vhost_call(dev, VHOST_GET_VRING_BASE, &state);
if (r < 0) { if (r < 0) {
fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r); fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
fflush(stderr); fflush(stderr);
...@@ -792,7 +791,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, ...@@ -792,7 +791,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
} }
file.fd = event_notifier_get_fd(&vq->masked_notifier); file.fd = event_notifier_get_fd(&vq->masked_notifier);
r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file); r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_CALL, &file);
if (r) { if (r) {
r = -errno; r = -errno;
goto fail_call; goto fail_call;
...@@ -813,14 +812,17 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, ...@@ -813,14 +812,17 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
{ {
uint64_t features; uint64_t features;
int i, r; int i, r;
hdev->control = (uintptr_t) opaque;;
r = ioctl(hdev->control, VHOST_SET_OWNER, NULL); if (hdev->vhost_ops->vhost_backend_init(hdev, opaque) < 0) {
return -errno;
}
r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL);
if (r < 0) { if (r < 0) {
goto fail; goto fail;
} }
r = ioctl(hdev->control, VHOST_GET_FEATURES, &features); r = hdev->vhost_ops->vhost_call(hdev, VHOST_GET_FEATURES, &features);
if (r < 0) { if (r < 0) {
goto fail; goto fail;
} }
...@@ -865,7 +867,7 @@ fail_vq: ...@@ -865,7 +867,7 @@ fail_vq:
} }
fail: fail:
r = -errno; r = -errno;
close(hdev->control); hdev->vhost_ops->vhost_backend_cleanup(hdev);
return r; return r;
} }
...@@ -878,7 +880,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev) ...@@ -878,7 +880,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
memory_listener_unregister(&hdev->memory_listener); memory_listener_unregister(&hdev->memory_listener);
g_free(hdev->mem); g_free(hdev->mem);
g_free(hdev->mem_sections); g_free(hdev->mem_sections);
close(hdev->control); hdev->vhost_ops->vhost_backend_cleanup(hdev);
} }
bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev) bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
...@@ -980,7 +982,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, ...@@ -980,7 +982,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
} else { } else {
file.fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq)); file.fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq));
} }
r = ioctl(hdev->control, VHOST_SET_VRING_CALL, &file); r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_VRING_CALL, &file);
assert(r >= 0); assert(r >= 0);
} }
...@@ -1022,7 +1024,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) ...@@ -1022,7 +1024,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
if (r < 0) { if (r < 0) {
goto fail_features; goto fail_features;
} }
r = ioctl(hdev->control, VHOST_SET_MEM_TABLE, hdev->mem); r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_MEM_TABLE, hdev->mem);
if (r < 0) { if (r < 0) {
r = -errno; r = -errno;
goto fail_mem; goto fail_mem;
...@@ -1041,8 +1043,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) ...@@ -1041,8 +1043,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
hdev->log_size = vhost_get_log_size(hdev); hdev->log_size = vhost_get_log_size(hdev);
hdev->log = hdev->log_size ? hdev->log = hdev->log_size ?
g_malloc0(hdev->log_size * sizeof *hdev->log) : NULL; g_malloc0(hdev->log_size * sizeof *hdev->log) : NULL;
r = ioctl(hdev->control, VHOST_SET_LOG_BASE, r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE, hdev->log);
(uint64_t)(unsigned long)hdev->log);
if (r < 0) { if (r < 0) {
r = -errno; r = -errno;
goto fail_log; goto fail_log;
......
/*
* vhost-backend
*
* Copyright (c) 2013 Virtual Open Systems Sarl.
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#ifndef VHOST_BACKEND_H_
#define VHOST_BACKEND_H_
struct vhost_dev;
typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
void *arg);
typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
typedef struct VhostOps {
vhost_call vhost_call;
vhost_backend_init vhost_backend_init;
vhost_backend_cleanup vhost_backend_cleanup;
} VhostOps;
#endif /* VHOST_BACKEND_H_ */
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define VHOST_H #define VHOST_H
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/virtio/vhost-backend.h"
#include "hw/virtio/virtio.h" #include "hw/virtio/virtio.h"
#include "exec/memory.h" #include "exec/memory.h"
...@@ -49,6 +50,7 @@ struct vhost_dev { ...@@ -49,6 +50,7 @@ struct vhost_dev {
bool memory_changed; bool memory_changed;
hwaddr mem_changed_start_addr; hwaddr mem_changed_start_addr;
hwaddr mem_changed_end_addr; hwaddr mem_changed_end_addr;
const VhostOps *vhost_ops;
}; };
int vhost_dev_init(struct vhost_dev *hdev, void *opaque, int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册