Skip to content

Commit 22027bd

Browse files
virtio: add API for VIRTIO devices and add VIRTIO PCI driver
This commit adds the API for accessing VIRTIO devices, and adds a driver for a VIRTIO PCIE device based on the newly added API. This commit is based on the Virtual I/O Device (VIRTIO) Version 1.3 specification: https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/virtio-v1.3-csd01.pdf Signed-off-by: Jakub Michalski <jmichalski@antmicro.com> Signed-off-by: Filip Kokosinski <fkokosinski@antmicro.com>
1 parent 5d74f78 commit 22027bd

File tree

12 files changed

+1379
-0
lines changed

12 files changed

+1379
-0
lines changed

MAINTAINERS.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,20 @@ Release Notes:
21762176
tests:
21772177
- drivers.video
21782178

2179+
"Drivers: VIRTIO":
2180+
status: maintained
2181+
maintainers:
2182+
- fkokosinski
2183+
- tgorochowik
2184+
collaborators:
2185+
- kgugala
2186+
files:
2187+
- drivers/virtio/
2188+
- dts/bindings/virtio/
2189+
- include/zephyr/virtio/
2190+
labels:
2191+
- "area: VIRTIO"
2192+
21792193
"Drivers: W1":
21802194
status: maintained
21812195
maintainers:

drivers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ add_subdirectory_ifdef(CONFIG_SYSCON syscon)
8989
add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer)
9090
add_subdirectory_ifdef(CONFIG_TEE tee)
9191
add_subdirectory_ifdef(CONFIG_VIDEO video)
92+
add_subdirectory_ifdef(CONFIG_VIRTIO virtio)
9293
add_subdirectory_ifdef(CONFIG_VIRTUALIZATION virtualization)
9394
add_subdirectory_ifdef(CONFIG_W1 w1)
9495
add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)

drivers/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ source "drivers/timer/Kconfig"
8888
source "drivers/usb/Kconfig"
8989
source "drivers/usb_c/Kconfig"
9090
source "drivers/video/Kconfig"
91+
source "drivers/virtio/Kconfig"
9192
source "drivers/virtualization/Kconfig"
9293
source "drivers/w1/Kconfig"
9394
source "drivers/watchdog/Kconfig"

drivers/virtio/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2024 Antmicro <www.antmicro.com>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
6+
zephyr_library_sources_ifdef(CONFIG_VIRTIO virtqueue.c virtio_common.c)
7+
zephyr_library_sources_ifdef(CONFIG_VIRTIO_PCI virtio_pci.c)

drivers/virtio/Kconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2024 Antmicro <www.antmicro.com>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config VIRTIO
5+
bool "support for VIRTIO"
6+
help
7+
Enable options for VIRTIO
8+
9+
if VIRTIO
10+
11+
config VIRTIO_PCI
12+
bool "support for VIRTIO over PCI"
13+
default y
14+
depends on DT_HAS_VIRTIO_PCI_ENABLED
15+
help
16+
Enable options for VIRTIO over PCI
17+
18+
endif # VIRTIO
19+
20+
module = VIRTIO
21+
module-str = VIRTIO
22+
source "subsys/logging/Kconfig.template.log_config"

drivers/virtio/virtio_common.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2025 Antmicro <www.antmicro.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/logging/log.h>
8+
#include <zephyr/sys/byteorder.h>
9+
#include <zephyr/virtio/virtio.h>
10+
#include <zephyr/virtio/virtqueue.h>
11+
#include "virtio_common.h"
12+
13+
LOG_MODULE_REGISTER(virtio_common, CONFIG_VIRTIO_LOG_LEVEL);
14+
15+
void virtio_isr(const struct device *dev, uint8_t isr_status, uint16_t virtqueue_count)
16+
{
17+
if (isr_status & VIRTIO_QUEUE_INTERRUPT) {
18+
for (int i = 0; i < virtqueue_count; i++) {
19+
struct virtq *vq = virtio_get_virtqueue(dev, i);
20+
uint16_t used_idx = sys_le16_to_cpu(vq->used->idx);
21+
22+
while (vq->last_used_idx != used_idx) {
23+
uint16_t idx = vq->last_used_idx % vq->num;
24+
uint16_t idx_le = sys_cpu_to_le16(idx);
25+
uint16_t chain_head_le = vq->used->ring[idx_le].id;
26+
uint16_t chain_head = sys_le16_to_cpu(chain_head_le);
27+
uint32_t used_len = sys_le32_to_cpu(
28+
vq->used->ring[idx_le].len
29+
);
30+
31+
/*
32+
* We are making a copy here, because chain will be
33+
* returned before invoking the callback and may be
34+
* overwritten by the time callback is called. This
35+
* is to allow callback to immediately place the
36+
* descriptors back in the avail_ring
37+
*/
38+
struct virtq_receive_callback_entry cbe =
39+
vq->recv_cbs[chain_head];
40+
41+
uint16_t next = chain_head;
42+
bool last = false;
43+
44+
/*
45+
* We are done processing the descriptor chain, and
46+
* we can add used descriptors back to the free stack.
47+
* The only thing left to do is calling the callback
48+
* associated with the chain, but it was saved above on
49+
* the stack, so other code is free to use the descriptors
50+
*/
51+
while (!last) {
52+
uint16_t curr = next;
53+
uint16_t curr_le = sys_cpu_to_le16(curr);
54+
55+
next = vq->desc[curr_le].next;
56+
last = !(vq->desc[curr_le].flags & VIRTQ_DESC_F_NEXT);
57+
virtq_add_free_desc(vq, curr);
58+
}
59+
60+
vq->last_used_idx++;
61+
62+
if (cbe.cb) {
63+
cbe.cb(cbe.opaque, used_len);
64+
}
65+
}
66+
}
67+
}
68+
if (isr_status & VIRTIO_DEVICE_CONFIGURATION_INTERRUPT) {
69+
LOG_ERR("device configuration change interrupt is currently unsupported");
70+
}
71+
}

drivers/virtio/virtio_common.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2025 Antmicro <www.antmicro.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_VIRTIO_VIRTIO_COMMON_H_
8+
#define ZEPHYR_VIRTIO_VIRTIO_COMMON_H_
9+
10+
#define DEVICE_STATUS_ACKNOWLEDGE 0
11+
#define DEVICE_STATUS_DRIVER 1
12+
#define DEVICE_STATUS_DRIVER_OK 2
13+
#define DEVICE_STATUS_FEATURES_OK 3
14+
#define DEVICE_STATUS_NEEDS_RESET 6
15+
#define DEVICE_STATUS_FAILED 7
16+
17+
#define VIRTIO_F_VERSION_1 32
18+
19+
/* Ranges of feature bits for specific device types (see spec 2.2)*/
20+
#define DEV_TYPE_FEAT_RANGE_0_BEGIN 0
21+
#define DEV_TYPE_FEAT_RANGE_0_END 23
22+
#define DEV_TYPE_FEAT_RANGE_1_BEGIN 50
23+
#define DEV_TYPE_FEAT_RANGE_1_END 127
24+
25+
/*
26+
* While defined separately in 4.1.4.5 for PCI and in 4.2.2 for MMIO
27+
* the same bits are responsible for the same interrupts, so defines
28+
* with them can be unified
29+
*/
30+
#define VIRTIO_QUEUE_INTERRUPT 1
31+
#define VIRTIO_DEVICE_CONFIGURATION_INTERRUPT 2
32+
33+
34+
/**
35+
* Common virtio isr
36+
*
37+
* @param dev virtio device it operates on
38+
* @param isr_status value of isr status register
39+
* @param virtqueue_count amount of available virtqueues
40+
*/
41+
void virtio_isr(const struct device *dev, uint8_t isr_status, uint16_t virtqueue_count);
42+
43+
#endif /*ZEPHYR_VIRTIO_VIRTIO_COMMON_H_*/

0 commit comments

Comments
 (0)