Add virtio transport driver for the 9P filesystem. This driver binds to the virtio-9p device exposed by the hypervisor and registers the transport operations with the 9P client framework. It implements the transmit and receive routines.
Signed-off-by: Kuan-Wei Chiu <[email protected]> --- drivers/virtio/Kconfig | 7 ++++ drivers/virtio/Makefile | 1 + drivers/virtio/virtio-uclass.c | 1 + drivers/virtio/virtio_9p.c | 75 ++++++++++++++++++++++++++++++++++ include/virtio.h | 4 +- 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 drivers/virtio/virtio_9p.c diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 512ac376f18..55b44428026 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -77,4 +77,11 @@ config VIRTIO_RNG help This is the virtual random number generator driver. It can be used with QEMU based targets. + +config VIRTIO_9P + bool "virtio 9P transport driver" + depends on VIRTIO && NET_9P + help + This enables the 9P transport driver over virtio. + It can be used with QEMU based targets. endmenu diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile index 4c63a6c6904..6e7bcfc8eaa 100644 --- a/drivers/virtio/Makefile +++ b/drivers/virtio/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_VIRTIO_SANDBOX) += virtio_sandbox.o obj-$(CONFIG_VIRTIO_NET) += virtio_net.o obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o obj-$(CONFIG_VIRTIO_RNG) += virtio_rng.o +obj-$(CONFIG_VIRTIO_9P) += virtio_9p.o diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c index a871a1439d4..c163b2fd7d5 100644 --- a/drivers/virtio/virtio-uclass.c +++ b/drivers/virtio/virtio-uclass.c @@ -30,6 +30,7 @@ static const char *const virtio_drv_name[VIRTIO_ID_MAX_NUM] = { [VIRTIO_ID_NET] = VIRTIO_NET_DRV_NAME, [VIRTIO_ID_BLOCK] = VIRTIO_BLK_DRV_NAME, [VIRTIO_ID_RNG] = VIRTIO_RNG_DRV_NAME, + [VIRTIO_ID_9P] = VIRTIO_9P_DRV_NAME, }; int virtio_get_config(struct udevice *vdev, unsigned int offset, diff --git a/drivers/virtio/virtio_9p.c b/drivers/virtio/virtio_9p.c new file mode 100644 index 00000000000..e37c9c37c4b --- /dev/null +++ b/drivers/virtio/virtio_9p.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026, Kuan-Wei Chiu <[email protected]> + */ + +#include <9p.h> +#include <dm.h> +#include <cpu_func.h> +#include <virtio.h> +#include <virtio_ring.h> +#include <virtio_types.h> +#include <asm/cache.h> + +struct virtio_9p_priv { + struct virtqueue *vq; + struct p9_client client; +}; + +static int virtio_9p_request(struct p9_client *c, void *tx, int tx_len, void *rx, int rx_len) +{ + struct virtio_9p_priv *priv = c->priv; + struct virtio_sg sg[2]; + struct virtio_sg *sgs[2]; + int len; + + sg[0].addr = tx; + sg[0].length = tx_len; + sgs[0] = &sg[0]; + + sg[1].addr = rx; + sg[1].length = rx_len; + sgs[1] = &sg[1]; + + flush_dcache_range((ulong)tx, ALIGN((ulong)tx + tx_len, ARCH_DMA_MINALIGN)); + flush_dcache_range((ulong)rx, ALIGN((ulong)rx + rx_len, ARCH_DMA_MINALIGN)); + + if (virtqueue_add(priv->vq, sgs, 1, 1)) + return -EIO; + + virtqueue_kick(priv->vq); + + while (!virtqueue_get_buf(priv->vq, &len)) + ; + + invalidate_dcache_range((ulong)rx, ALIGN((ulong)rx + rx_len, ARCH_DMA_MINALIGN)); + + return 0; +} + +static const struct p9_trans_ops virtio_9p_ops = { + .request = virtio_9p_request, +}; + +static int virtio_9p_probe(struct udevice *dev) +{ + struct virtio_9p_priv *priv = dev_get_priv(dev); + int ret; + + ret = virtio_find_vqs(dev, 1, &priv->vq); + if (ret) + return ret; + + priv->client.ops = &virtio_9p_ops; + priv->client.priv = priv; + p9_register_client(&priv->client); + + return 0; +} + +U_BOOT_DRIVER(virtio_9p) = { + .name = VIRTIO_9P_DRV_NAME, + .id = UCLASS_MISC, + .probe = virtio_9p_probe, + .priv_auto = sizeof(struct virtio_9p_priv), +}; diff --git a/include/virtio.h b/include/virtio.h index 3edf023463d..7b3f466220f 100644 --- a/include/virtio.h +++ b/include/virtio.h @@ -31,11 +31,13 @@ #define VIRTIO_ID_NET 1 /* virtio net */ #define VIRTIO_ID_BLOCK 2 /* virtio block */ #define VIRTIO_ID_RNG 4 /* virtio rng */ -#define VIRTIO_ID_MAX_NUM 5 +#define VIRTIO_ID_9P 9 /* virtio 9p */ +#define VIRTIO_ID_MAX_NUM 10 #define VIRTIO_NET_DRV_NAME "virtio-net" #define VIRTIO_BLK_DRV_NAME "virtio-blk" #define VIRTIO_RNG_DRV_NAME "virtio-rng" +#define VIRTIO_9P_DRV_NAME "virtio-9p" /* Status byte for guest to report progress, and synchronize features */ -- 2.55.0.rc2.803.g1fd1e6609c-goog

