Skip to content

Commit bb34ffe

Browse files
chejianjlijinxia
authored andcommitted
dm: virtio: add vhost support
This patch adds the vhost support to the device model virtio. A vhost proxy is implemented based on the virtio framework and vhost char dev. Key data structures and external interfaces are implemented in this patch. Tracked-On: #1329 Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent 781e7df commit bb34ffe

File tree

3 files changed

+465
-0
lines changed

3 files changed

+465
-0
lines changed

devicemodel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ SRCS += hw/usb_core.c
6262
SRCS += hw/uart_core.c
6363
SRCS += hw/pci/virtio/virtio.c
6464
SRCS += hw/pci/virtio/virtio_kernel.c
65+
SRCS += hw/pci/virtio/vhost.c
6566
SRCS += hw/platform/usb_mouse.c
6667
SRCS += hw/platform/usb_pmapper.c
6768
SRCS += hw/platform/atkbdc.c

devicemodel/hw/pci/virtio/vhost.c

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
/*
2+
* Copyright (C) 2018 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*
6+
*/
7+
8+
#include <sys/cdefs.h>
9+
#include <sys/param.h>
10+
#include <sys/uio.h>
11+
#include <sys/ioctl.h>
12+
#include <sys/eventfd.h>
13+
#include <errno.h>
14+
#include <stdarg.h>
15+
#include <stdlib.h>
16+
#include <stdio.h>
17+
#include <stdint.h>
18+
#include <unistd.h>
19+
#include <pthread.h>
20+
#include <linux/vhost.h>
21+
22+
#include "dm.h"
23+
#include "pci_core.h"
24+
#include "irq.h"
25+
#include "vmmapi.h"
26+
#include "vhost.h"
27+
28+
static int vhost_debug;
29+
#define LOG_TAG "vhost: "
30+
#define DPRINTF(fmt, args...) \
31+
do { if (vhost_debug) printf(LOG_TAG fmt, ##args); } while (0)
32+
#define WPRINTF(fmt, args...) printf(LOG_TAG fmt, ##args)
33+
34+
static void
35+
vhost_kernel_init(struct vhost_dev *vdev, struct virtio_base *base,
36+
int fd, int vq_idx, uint32_t busyloop_timeout)
37+
{
38+
/* to be implemented */
39+
}
40+
41+
static void
42+
vhost_kernel_deinit(struct vhost_dev *vdev)
43+
{
44+
/* to be implemented */
45+
}
46+
47+
static int
48+
vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *vdev,
49+
struct vhost_vring_state *s)
50+
{
51+
/* to be implemented */
52+
return -1;
53+
}
54+
55+
static int
56+
vhost_kernel_set_features(struct vhost_dev *vdev,
57+
uint64_t features)
58+
{
59+
/* to be implemented */
60+
return -1;
61+
}
62+
63+
static int
64+
vhost_kernel_get_features(struct vhost_dev *vdev,
65+
uint64_t *features)
66+
{
67+
/* to be implemented */
68+
return -1;
69+
}
70+
71+
static int
72+
vhost_kernel_set_owner(struct vhost_dev *vdev)
73+
{
74+
/* to be implemented */
75+
return -1;
76+
}
77+
78+
static int
79+
vhost_kernel_reset_device(struct vhost_dev *vdev)
80+
{
81+
/* to be implemented */
82+
return -1;
83+
}
84+
85+
static int
86+
vhost_kernel_net_set_backend(struct vhost_dev *vdev,
87+
struct vhost_vring_file *file)
88+
{
89+
/* to be implemented */
90+
return -1;
91+
}
92+
93+
static int
94+
vhost_vq_init(struct vhost_dev *vdev, int idx)
95+
{
96+
/* to be implemented */
97+
return -1;
98+
}
99+
100+
static int
101+
vhost_vq_deinit(struct vhost_vq *vq)
102+
{
103+
/* to be implemented */
104+
return -1;
105+
}
106+
107+
static int
108+
vhost_vq_start(struct vhost_dev *vdev, int idx)
109+
{
110+
/* to be implemented */
111+
return -1;
112+
}
113+
114+
static int
115+
vhost_vq_stop(struct vhost_dev *vdev, int idx)
116+
{
117+
/* to be implemented */
118+
return -1;
119+
}
120+
121+
static int
122+
vhost_set_mem_table(struct vhost_dev *vdev)
123+
{
124+
/* to be implemented */
125+
return -1;
126+
}
127+
128+
int
129+
vhost_dev_init(struct vhost_dev *vdev,
130+
struct virtio_base *base,
131+
int fd,
132+
int vq_idx,
133+
uint64_t vhost_features,
134+
uint64_t vhost_ext_features,
135+
uint32_t busyloop_timeout)
136+
{
137+
uint64_t features;
138+
int i, rc;
139+
140+
/* sanity check */
141+
if (!base || !base->queues || !base->vops) {
142+
WPRINTF("virtio_base is not initialized\n");
143+
goto fail;
144+
}
145+
146+
if (!vdev->vqs || vdev->nvqs == 0) {
147+
WPRINTF("virtqueue is not initialized\n");
148+
goto fail;
149+
}
150+
151+
if (vq_idx + vdev->nvqs > base->vops->nvq) {
152+
WPRINTF("invalid vq_idx: %d\n", vq_idx);
153+
goto fail;
154+
}
155+
156+
vhost_kernel_init(vdev, base, fd, vq_idx, busyloop_timeout);
157+
158+
rc = vhost_kernel_get_features(vdev, &features);
159+
if (rc < 0) {
160+
WPRINTF("vhost_get_features failed\n");
161+
goto fail;
162+
}
163+
164+
for (i = 0; i < vdev->nvqs; i++) {
165+
rc = vhost_vq_init(vdev, i);
166+
if (rc < 0)
167+
goto fail;
168+
}
169+
170+
/* specific backend features to vhost */
171+
vdev->vhost_ext_features = vhost_ext_features & features;
172+
173+
/* features supported by vhost */
174+
vdev->vhost_features = vhost_features & features;
175+
176+
/*
177+
* If the features bits are not supported by either vhost kernel
178+
* mediator or configuration of device model(specified by
179+
* vhost_features), they should be disabled in device_caps,
180+
* which expose as virtio host_features for virtio FE driver.
181+
*/
182+
vdev->base->device_caps &= ~(vhost_features ^ features);
183+
vdev->started = false;
184+
185+
return 0;
186+
187+
fail:
188+
vhost_dev_deinit(vdev);
189+
return -1;
190+
}
191+
192+
int
193+
vhost_dev_deinit(struct vhost_dev *vdev)
194+
{
195+
int i;
196+
197+
if (!vdev->base || !vdev->base->queues || !vdev->base->vops)
198+
return -1;
199+
200+
for (i = 0; i < vdev->nvqs; i++)
201+
vhost_vq_deinit(&vdev->vqs[i]);
202+
203+
vhost_kernel_deinit(vdev);
204+
205+
return 0;
206+
}
207+
208+
int
209+
vhost_dev_start(struct vhost_dev *vdev)
210+
{
211+
struct vhost_vring_state state;
212+
uint64_t features;
213+
int i, rc;
214+
215+
if (vdev->started)
216+
return 0;
217+
218+
/* sanity check */
219+
if (!vdev->base || !vdev->base->queues || !vdev->base->vops) {
220+
WPRINTF("virtio_base is not initialized\n");
221+
goto fail;
222+
}
223+
224+
if ((vdev->base->status & VIRTIO_CR_STATUS_DRIVER_OK) == 0) {
225+
WPRINTF("status error 0x%x\n", vdev->base->status);
226+
goto fail;
227+
}
228+
229+
rc = vhost_kernel_set_owner(vdev);
230+
if (rc < 0) {
231+
WPRINTF("vhost_set_owner failed\n");
232+
goto fail;
233+
}
234+
235+
/* set vhost internal features */
236+
features = (vdev->base->negotiated_caps & vdev->vhost_features) |
237+
vdev->vhost_ext_features;
238+
rc = vhost_kernel_set_features(vdev, features);
239+
if (rc < 0) {
240+
WPRINTF("set_features failed\n");
241+
goto fail;
242+
}
243+
DPRINTF("set_features: 0x%lx\n", features);
244+
245+
/* set memory table */
246+
rc = vhost_set_mem_table(vdev);
247+
if (rc < 0) {
248+
WPRINTF("set_mem_table failed\n");
249+
goto fail;
250+
}
251+
252+
/* config busyloop timeout */
253+
if (vdev->busyloop_timeout) {
254+
state.num = vdev->busyloop_timeout;
255+
for (i = 0; i < vdev->nvqs; i++) {
256+
state.index = i;
257+
rc = vhost_kernel_set_vring_busyloop_timeout(vdev,
258+
&state);
259+
if (rc < 0) {
260+
WPRINTF("set_busyloop_timeout failed\n");
261+
goto fail;
262+
}
263+
}
264+
}
265+
266+
/* start vhost virtqueue */
267+
for (i = 0; i < vdev->nvqs; i++) {
268+
rc = vhost_vq_start(vdev, i);
269+
if (rc < 0)
270+
goto fail_vq;
271+
}
272+
273+
vdev->started = true;
274+
return 0;
275+
276+
fail_vq:
277+
while (--i >= 0)
278+
vhost_vq_stop(vdev, i);
279+
fail:
280+
return -1;
281+
}
282+
283+
int
284+
vhost_dev_stop(struct vhost_dev *vdev)
285+
{
286+
int i, rc = 0;
287+
288+
for (i = 0; i < vdev->nvqs; i++)
289+
vhost_vq_stop(vdev, i);
290+
291+
/* the following are done by this ioctl:
292+
* 1) resources of the vhost dev are freed
293+
* 2) vhost virtqueues are reset
294+
*/
295+
rc = vhost_kernel_reset_device(vdev);
296+
if (rc < 0) {
297+
WPRINTF("vhost_reset_device failed\n");
298+
rc = -1;
299+
}
300+
301+
vdev->started = false;
302+
return rc;
303+
}
304+
305+
int
306+
vhost_net_set_backend(struct vhost_dev *vdev, int backend_fd)
307+
{
308+
struct vhost_vring_file file;
309+
int rc, i;
310+
311+
file.fd = backend_fd;
312+
for (i = 0; i < vdev->nvqs; i++) {
313+
file.index = i;
314+
rc = vhost_kernel_net_set_backend(vdev, &file);
315+
if (rc < 0)
316+
goto fail;
317+
}
318+
319+
return 0;
320+
fail:
321+
file.fd = -1;
322+
while (--i >= 0) {
323+
file.index = i;
324+
vhost_kernel_net_set_backend(vdev, &file);
325+
}
326+
327+
return -1;
328+
}

0 commit comments

Comments
 (0)