Skip to content

Commit 986ef95

Browse files
committed
samples: drivers: virtualization: add vhost sample application
Add sample application demonstrating vhost driver usage for VIRTIO backend implementations. Includes basic setup and configuration examples for Xen MMIO VirtIO backend. Signed-off-by: TOKITA Hiroshi <[email protected]>
1 parent c9368aa commit 986ef95

File tree

7 files changed

+215
-0
lines changed

7 files changed

+215
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(vhost)
7+
8+
target_sources(app PRIVATE src/main.c)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
.. zephyr:code-sample:: vhost
2+
:name: Vhost sample application
3+
4+
Overview
5+
********
6+
7+
This sample demonstrates the use of the vhost driver subsystem for implementing
8+
VIRTIO backends in Zephyr. The application shows how to:
9+
10+
* Initialize and configure vhost devices
11+
* Handle VIRTIO queue operations
12+
* Process guest requests using the vringh utility
13+
* Implement a basic VIRTIO backend for Xen virtualization
14+
15+
The sample sets up a vhost device that can communicate with VIRTIO frontend
16+
drivers in guest virtual machines, specifically designed for Xen MMIO
17+
virtualization environments.
18+
19+
Requirements
20+
************
21+
22+
This sample requires:
23+
24+
* A Xen hypervisor environment
25+
* Xen domain management tools
26+
* A board that supports Xen virtualization (e.g., xenvm)
27+
28+
Building and Running
29+
********************
30+
31+
This application can be built and executed on Xen as follows:
32+
33+
.. zephyr-app-commands::
34+
:zephyr-app: samples/drivers/virtualization/vhost
35+
:host-os: unix
36+
:board: xenvm
37+
:goals: run
38+
:compact:
39+
40+
The application will initialize the vhost subsystem and wait for VIRTIO
41+
frontend connections from guest domains. When a guest connects and sends
42+
requests, the sample will process them and provide responses.
43+
44+
Expected Output
45+
***************
46+
47+
When running successfully, you should see output similar to::
48+
49+
*** Booting Zephyr OS build zephyr-v3.x.x ***
50+
[00:00:00.000,000] <inf> vhost: VHost device ready
51+
[00:00:00.000,000] <dbg> vhost: queue_ready_handler(dev=0x..., qid=0, data=0x...)
52+
[00:00:00.000,000] <dbg> vhost: vringh_handler: queue_id=0
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
vhost: xen-vhost-mmio {
9+
compatible = "xen,vhost-mmio";
10+
device-id = <4>;
11+
vendor-id = <0x7a707972>; /* "zphy" */
12+
num-queues = <2>;
13+
queue-size-max= <16>;
14+
base = <0x2000000>;
15+
};
16+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright (c) 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "xenvm.overlay"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONFIG_VHOST=y
2+
CONFIG_LOG=y
3+
CONFIG_HEAP_MEM_POOL_SIZE=8388608
4+
CONFIG_LOG_MODE_IMMEDIATE=y
5+
CONFIG_LOG_DEFAULT_LEVEL=3
6+
CONFIG_VHOST_LOG_LEVEL_DBG=y
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
sample:
2+
description: VHost driver sample for VIRTIO backend implementation
3+
name: vhost
4+
common:
5+
integration_platforms:
6+
- xenvm
7+
platform_allow: xenvm
8+
harness: console
9+
harness_config:
10+
type: multi_line
11+
regex:
12+
- "VHost device ready"
13+
- "VHost sample application started"
14+
timeout: 60
15+
depends_on: vhost
16+
tests:
17+
sample.drivers.virtualization.vhost:
18+
tags: drivers virtualization vhost xen
19+
min_ram: 32
20+
extra_args: CONFIG_LOG_MODE_IMMEDIATE=y
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/vhost.h>
8+
#include <zephyr/drivers/vhost/vringh.h>
9+
#include <zephyr/logging/log.h>
10+
11+
LOG_MODULE_REGISTER(vhost);
12+
13+
struct vhost_iovec riovec[16];
14+
struct vhost_iovec wiovec[16];
15+
16+
struct vringh_iov riov = {
17+
.iov = riovec,
18+
.max_num = 16,
19+
};
20+
21+
struct vringh_iov wiov = {
22+
.iov = wiovec,
23+
.max_num = 16,
24+
};
25+
26+
struct vringh vrh_inst;
27+
28+
void vringh_handler(struct vringh *vrh)
29+
{
30+
LOG_DBG("%s: queue_id=%lu", __func__, vrh->queue_id);
31+
uint16_t head;
32+
33+
while (true) {
34+
int ret = vringh_getdesc(vrh, &riov, &wiov, &head);
35+
36+
if (ret < 0) {
37+
LOG_ERR("vringh_getdesc failed: %d", ret);
38+
return;
39+
}
40+
41+
if (ret == 0) {
42+
return;
43+
}
44+
45+
/* Process writable iovecs */
46+
for (uint32_t s = 0; s < wiov.used; s++) {
47+
uint8_t *dst = wiov.iov[s].iov_base;
48+
uint32_t len = wiov.iov[s].iov_len;
49+
50+
LOG_DBG("%s: addr=%p len=%u", __func__, dst, len);
51+
52+
for (uint32_t i = 0; i < len; i++) {
53+
sys_write8(i, (mem_addr_t)&dst[i]);
54+
}
55+
}
56+
57+
barrier_dmem_fence_full();
58+
59+
uint32_t total_len = 0;
60+
for (uint32_t i = 0; i < wiov.used; i++) {
61+
total_len += wiov.iov[i].iov_len;
62+
}
63+
64+
vringh_complete(vrh, head, total_len);
65+
66+
if (vringh_need_notify(vrh) > 0) {
67+
vringh_notify(vrh);
68+
}
69+
70+
/* Reset iovecs for next iteration */
71+
vringh_iov_reset(&riov);
72+
vringh_iov_reset(&wiov);
73+
}
74+
}
75+
76+
void queue_ready_handler(const struct device *dev, uint16_t qid, void *data)
77+
{
78+
LOG_DBG("%s(dev=%p, qid=%u, data=%p)", __func__, dev, qid, data);
79+
80+
/* Initialize iovecs before descriptor processing */
81+
vringh_iov_init(&riov, riov.iov, riov.max_num);
82+
vringh_iov_init(&wiov, wiov.iov, wiov.max_num);
83+
84+
int err = vringh_init_device(&vrh_inst, dev, qid, vringh_handler);
85+
if (err) {
86+
LOG_ERR("vringh_init_device failed: %d", err);
87+
return;
88+
}
89+
}
90+
91+
int main(void)
92+
{
93+
const struct device *device = DEVICE_DT_GET(DT_NODELABEL(vhost));
94+
95+
if (!device_is_ready(device)) {
96+
LOG_ERR("VHost device not ready");
97+
return -ENODEV;
98+
}
99+
100+
LOG_INF("VHost device ready");
101+
vhost_set_ready_callback(device, queue_ready_handler, (void *)device);
102+
103+
LOG_INF("VHost sample application started, waiting for guest connections...");
104+
k_sleep(K_FOREVER);
105+
return 0;
106+
}

0 commit comments

Comments
 (0)