Browse Source

Add vhost-user-backend

Create a vhost-user-backend object that holds a connection to a
vhost-user backend (or "slave" process) and can be referenced from
virtio devices that support it. See later patches for input & gpu
usage.

Note: a previous iteration of this object made it user-creatable, and
allowed managed sub-process spawning, but that has been dropped for
now.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 2019050313.24916-4-marcandre.lureau@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
master
Marc-André Lureau 1 month ago
parent
commit
f24bb7287d
4 changed files with 270 additions and 0 deletions
  1. 2
    0
      MAINTAINERS
  2. 2
    0
      backends/Makefile.objs
  3. 209
    0
      backends/vhost-user.c
  4. 57
    0
      include/sysemu/vhost-user-backend.h

+ 2
- 0
MAINTAINERS View File

@@ -1478,6 +1478,8 @@ F: hw/*/*vhost*
1478 1478
 F: docs/interop/vhost-user.json
1479 1479
 F: docs/interop/vhost-user.txt
1480 1480
 F: contrib/vhost-user-*/
1481
+F: backends/vhost-user.c
1482
+F: include/sysemu/vhost-user-backend.h
1481 1483
 
1482 1484
 virtio
1483 1485
 M: Michael S. Tsirkin <mst@redhat.com>

+ 2
- 0
backends/Makefile.objs View File

@@ -14,4 +14,6 @@ common-obj-y += cryptodev-vhost.o
14 14
 common-obj-$(CONFIG_VHOST_CRYPTO) += cryptodev-vhost-user.o
15 15
 endif
16 16
 
17
+common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_VIRTIO)) += vhost-user.o
18
+
17 19
 common-obj-$(CONFIG_LINUX) += hostmem-memfd.o

+ 209
- 0
backends/vhost-user.c View File

@@ -0,0 +1,209 @@
1
+/*
2
+ * QEMU vhost-user backend
3
+ *
4
+ * Copyright (C) 2018 Red Hat Inc
5
+ *
6
+ * Authors:
7
+ *  Marc-André Lureau <marcandre.lureau@redhat.com>
8
+ *
9
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
+ * See the COPYING file in the top-level directory.
11
+ */
12
+
13
+
14
+#include "qemu/osdep.h"
15
+#include "hw/qdev.h"
16
+#include "qapi/error.h"
17
+#include "qapi/qmp/qerror.h"
18
+#include "qemu/error-report.h"
19
+#include "qom/object_interfaces.h"
20
+#include "sysemu/vhost-user-backend.h"
21
+#include "sysemu/kvm.h"
22
+#include "io/channel-command.h"
23
+#include "hw/virtio/virtio-bus.h"
24
+
25
+static bool
26
+ioeventfd_enabled(void)
27
+{
28
+    return kvm_enabled() && kvm_eventfds_enabled();
29
+}
30
+
31
+int
32
+vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
33
+                            unsigned nvqs, Error **errp)
34
+{
35
+    int ret;
36
+
37
+    assert(!b->vdev && vdev);
38
+
39
+    if (!ioeventfd_enabled()) {
40
+        error_setg(errp, "vhost initialization failed: requires kvm");
41
+        return -1;
42
+    }
43
+
44
+    if (!vhost_user_init(&b->vhost_user, &b->chr, errp)) {
45
+        return -1;
46
+    }
47
+
48
+    b->vdev = vdev;
49
+    b->dev.nvqs = nvqs;
50
+    b->dev.vqs = g_new(struct vhost_virtqueue, nvqs);
51
+
52
+    ret = vhost_dev_init(&b->dev, &b->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
53
+    if (ret < 0) {
54
+        error_setg_errno(errp, -ret, "vhost initialization failed");
55
+        return -1;
56
+    }
57
+
58
+    return 0;
59
+}
60
+
61
+void
62
+vhost_user_backend_start(VhostUserBackend *b)
63
+{
64
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev)));
65
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
66
+    int ret, i ;
67
+
68
+    if (b->started) {
69
+        return;
70
+    }
71
+
72
+    if (!k->set_guest_notifiers) {
73
+        error_report("binding does not support guest notifiers");
74
+        return;
75
+    }
76
+
77
+    ret = vhost_dev_enable_notifiers(&b->dev, b->vdev);
78
+    if (ret < 0) {
79
+        return;
80
+    }
81
+
82
+    ret = k->set_guest_notifiers(qbus->parent, b->dev.nvqs, true);
83
+    if (ret < 0) {
84
+        error_report("Error binding guest notifier");
85
+        goto err_host_notifiers;
86
+    }
87
+
88
+    b->dev.acked_features = b->vdev->guest_features;
89
+    ret = vhost_dev_start(&b->dev, b->vdev);
90
+    if (ret < 0) {
91
+        error_report("Error start vhost dev");
92
+        goto err_guest_notifiers;
93
+    }
94
+
95
+    /* guest_notifier_mask/pending not used yet, so just unmask
96
+     * everything here.  virtio-pci will do the right thing by
97
+     * enabling/disabling irqfd.
98
+     */
99
+    for (i = 0; i < b->dev.nvqs; i++) {
100
+        vhost_virtqueue_mask(&b->dev, b->vdev,
101
+                             b->dev.vq_index + i, false);
102
+    }
103
+
104
+    b->started = true;
105
+    return;
106
+
107
+err_guest_notifiers:
108
+    k->set_guest_notifiers(qbus->parent, b->dev.nvqs, false);
109
+err_host_notifiers:
110
+    vhost_dev_disable_notifiers(&b->dev, b->vdev);
111
+}
112
+
113
+void
114
+vhost_user_backend_stop(VhostUserBackend *b)
115
+{
116
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev)));
117
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
118
+    int ret = 0;
119
+
120
+    if (!b->started) {
121
+        return;
122
+    }
123
+
124
+    vhost_dev_stop(&b->dev, b->vdev);
125
+
126
+    if (k->set_guest_notifiers) {
127
+        ret = k->set_guest_notifiers(qbus->parent,
128
+                                     b->dev.nvqs, false);
129
+        if (ret < 0) {
130
+            error_report("vhost guest notifier cleanup failed: %d", ret);
131
+        }
132
+    }
133
+    assert(ret >= 0);
134
+
135
+    vhost_dev_disable_notifiers(&b->dev, b->vdev);
136
+    b->started = false;
137
+}
138
+
139
+static void set_chardev(Object *obj, const char *value, Error **errp)
140
+{
141
+    VhostUserBackend *b = VHOST_USER_BACKEND(obj);
142
+    Chardev *chr;
143
+
144
+    if (b->completed) {
145
+        error_setg(errp, QERR_PERMISSION_DENIED);
146
+        return;
147
+    }
148
+
149
+    g_free(b->chr_name);
150
+    b->chr_name = g_strdup(value);
151
+
152
+    chr = qemu_chr_find(b->chr_name);
153
+    if (chr == NULL) {
154
+        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
155
+                  "Chardev '%s' not found", b->chr_name);
156
+        return;
157
+    }
158
+
159
+    if (!qemu_chr_fe_init(&b->chr, chr, errp)) {
160
+        return;
161
+    }
162
+
163
+    b->completed = true;
164
+    /* could call vhost_dev_init() so early message can be exchanged */
165
+}
166
+
167
+static char *get_chardev(Object *obj, Error **errp)
168
+{
169
+    VhostUserBackend *b = VHOST_USER_BACKEND(obj);
170
+    Chardev *chr = qemu_chr_fe_get_driver(&b->chr);
171
+
172
+    if (chr && chr->label) {
173
+        return g_strdup(chr->label);
174
+    }
175
+
176
+    return NULL;
177
+}
178
+
179
+static void vhost_user_backend_init(Object *obj)
180
+{
181
+    object_property_add_str(obj, "chardev", get_chardev, set_chardev, NULL);
182
+}
183
+
184
+static void vhost_user_backend_finalize(Object *obj)
185
+{
186
+    VhostUserBackend *b = VHOST_USER_BACKEND(obj);
187
+
188
+    g_free(b->dev.vqs);
189
+    g_free(b->chr_name);
190
+
191
+    vhost_user_cleanup(&b->vhost_user);
192
+    qemu_chr_fe_deinit(&b->chr, true);
193
+}
194
+
195
+static const TypeInfo vhost_user_backend_info = {
196
+    .name = TYPE_VHOST_USER_BACKEND,
197
+    .parent = TYPE_OBJECT,
198
+    .instance_size = sizeof(VhostUserBackend),
199
+    .instance_init = vhost_user_backend_init,
200
+    .instance_finalize = vhost_user_backend_finalize,
201
+    .class_size = sizeof(VhostUserBackendClass),
202
+};
203
+
204
+static void register_types(void)
205
+{
206
+    type_register_static(&vhost_user_backend_info);
207
+}
208
+
209
+type_init(register_types);

+ 57
- 0
include/sysemu/vhost-user-backend.h View File

@@ -0,0 +1,57 @@
1
+/*
2
+ * QEMU vhost-user backend
3
+ *
4
+ * Copyright (C) 2018 Red Hat Inc
5
+ *
6
+ * Authors:
7
+ *  Marc-André Lureau <marcandre.lureau@redhat.com>
8
+ *
9
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
+ * See the COPYING file in the top-level directory.
11
+ */
12
+#ifndef QEMU_VHOST_USER_BACKEND_H
13
+#define QEMU_VHOST_USER_BACKEND_H
14
+
15
+#include "qom/object.h"
16
+#include "exec/memory.h"
17
+#include "qemu/option.h"
18
+#include "qemu/bitmap.h"
19
+#include "hw/virtio/vhost.h"
20
+#include "hw/virtio/vhost-user.h"
21
+#include "chardev/char-fe.h"
22
+#include "io/channel.h"
23
+
24
+#define TYPE_VHOST_USER_BACKEND "vhost-user-backend"
25
+#define VHOST_USER_BACKEND(obj) \
26
+    OBJECT_CHECK(VhostUserBackend, (obj), TYPE_VHOST_USER_BACKEND)
27
+#define VHOST_USER_BACKEND_GET_CLASS(obj) \
28
+    OBJECT_GET_CLASS(VhostUserBackendClass, (obj), TYPE_VHOST_USER_BACKEND)
29
+#define VHOST_USER_BACKEND_CLASS(klass) \
30
+    OBJECT_CLASS_CHECK(VhostUserBackendClass, (klass), TYPE_VHOST_USER_BACKEND)
31
+
32
+typedef struct VhostUserBackend VhostUserBackend;
33
+typedef struct VhostUserBackendClass VhostUserBackendClass;
34
+
35
+struct VhostUserBackendClass {
36
+    ObjectClass parent_class;
37
+};
38
+
39
+struct VhostUserBackend {
40
+    /* private */
41
+    Object parent;
42
+
43
+    char *chr_name;
44
+    CharBackend chr;
45
+    VhostUserState vhost_user;
46
+    struct vhost_dev dev;
47
+    VirtIODevice *vdev;
48
+    bool started;
49
+    bool completed;
50
+};
51
+
52
+int vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
53
+                                unsigned nvqs, Error **errp);
54
+void vhost_user_backend_start(VhostUserBackend *b);
55
+void vhost_user_backend_stop(VhostUserBackend *b);
56
+
57
+#endif

Loading…
Cancel
Save