162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci.. _writing_virtio_drivers:
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci======================
662306a36Sopenharmony_ciWriting Virtio Drivers
762306a36Sopenharmony_ci======================
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciIntroduction
1062306a36Sopenharmony_ci============
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciThis document serves as a basic guideline for driver programmers that
1362306a36Sopenharmony_cineed to hack a new virtio driver or understand the essentials of the
1462306a36Sopenharmony_ciexisting ones. See :ref:`Virtio on Linux <virtio>` for a general
1562306a36Sopenharmony_cioverview of virtio.
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciDriver boilerplate
1962306a36Sopenharmony_ci==================
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciAs a bare minimum, a virtio driver needs to register in the virtio bus
2262306a36Sopenharmony_ciand configure the virtqueues for the device according to its spec, the
2362306a36Sopenharmony_ciconfiguration of the virtqueues in the driver side must match the
2462306a36Sopenharmony_civirtqueue definitions in the device. A basic driver skeleton could look
2562306a36Sopenharmony_cilike this::
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	#include <linux/virtio.h>
2862306a36Sopenharmony_ci	#include <linux/virtio_ids.h>
2962306a36Sopenharmony_ci	#include <linux/virtio_config.h>
3062306a36Sopenharmony_ci	#include <linux/module.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	/* device private data (one per device) */
3362306a36Sopenharmony_ci	struct virtio_dummy_dev {
3462306a36Sopenharmony_ci		struct virtqueue *vq;
3562306a36Sopenharmony_ci	};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	static void virtio_dummy_recv_cb(struct virtqueue *vq)
3862306a36Sopenharmony_ci	{
3962306a36Sopenharmony_ci		struct virtio_dummy_dev *dev = vq->vdev->priv;
4062306a36Sopenharmony_ci		char *buf;
4162306a36Sopenharmony_ci		unsigned int len;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci		while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) {
4462306a36Sopenharmony_ci			/* process the received data */
4562306a36Sopenharmony_ci		}
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	static int virtio_dummy_probe(struct virtio_device *vdev)
4962306a36Sopenharmony_ci	{
5062306a36Sopenharmony_ci		struct virtio_dummy_dev *dev = NULL;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci		/* initialize device data */
5362306a36Sopenharmony_ci		dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL);
5462306a36Sopenharmony_ci		if (!dev)
5562306a36Sopenharmony_ci			return -ENOMEM;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci		/* the device has a single virtqueue */
5862306a36Sopenharmony_ci		dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, "input");
5962306a36Sopenharmony_ci		if (IS_ERR(dev->vq)) {
6062306a36Sopenharmony_ci			kfree(dev);
6162306a36Sopenharmony_ci			return PTR_ERR(dev->vq);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci		}
6462306a36Sopenharmony_ci		vdev->priv = dev;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		/* from this point on, the device can notify and get callbacks */
6762306a36Sopenharmony_ci		virtio_device_ready(vdev);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci		return 0;
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	static void virtio_dummy_remove(struct virtio_device *vdev)
7362306a36Sopenharmony_ci	{
7462306a36Sopenharmony_ci		struct virtio_dummy_dev *dev = vdev->priv;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		/*
7762306a36Sopenharmony_ci		 * disable vq interrupts: equivalent to
7862306a36Sopenharmony_ci		 * vdev->config->reset(vdev)
7962306a36Sopenharmony_ci		 */
8062306a36Sopenharmony_ci		virtio_reset_device(vdev);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci		/* detach unused buffers */
8362306a36Sopenharmony_ci		while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) {
8462306a36Sopenharmony_ci			kfree(buf);
8562306a36Sopenharmony_ci		}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci		/* remove virtqueues */
8862306a36Sopenharmony_ci		vdev->config->del_vqs(vdev);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci		kfree(dev);
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	static const struct virtio_device_id id_table[] = {
9462306a36Sopenharmony_ci		{ VIRTIO_ID_DUMMY, VIRTIO_DEV_ANY_ID },
9562306a36Sopenharmony_ci		{ 0 },
9662306a36Sopenharmony_ci	};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	static struct virtio_driver virtio_dummy_driver = {
9962306a36Sopenharmony_ci		.driver.name =  KBUILD_MODNAME,
10062306a36Sopenharmony_ci		.driver.owner = THIS_MODULE,
10162306a36Sopenharmony_ci		.id_table =     id_table,
10262306a36Sopenharmony_ci		.probe =        virtio_dummy_probe,
10362306a36Sopenharmony_ci		.remove =       virtio_dummy_remove,
10462306a36Sopenharmony_ci	};
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	module_virtio_driver(virtio_dummy_driver);
10762306a36Sopenharmony_ci	MODULE_DEVICE_TABLE(virtio, id_table);
10862306a36Sopenharmony_ci	MODULE_DESCRIPTION("Dummy virtio driver");
10962306a36Sopenharmony_ci	MODULE_LICENSE("GPL");
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ciThe device id ``VIRTIO_ID_DUMMY`` here is a placeholder, virtio drivers
11262306a36Sopenharmony_cishould be added only for devices that are defined in the spec, see
11362306a36Sopenharmony_ciinclude/uapi/linux/virtio_ids.h. Device ids need to be at least reserved
11462306a36Sopenharmony_ciin the virtio spec before being added to that file.
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciIf your driver doesn't have to do anything special in its ``init`` and
11762306a36Sopenharmony_ci``exit`` methods, you can use the module_virtio_driver() helper to
11862306a36Sopenharmony_cireduce the amount of boilerplate code.
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciThe ``probe`` method does the minimum driver setup in this case
12162306a36Sopenharmony_ci(memory allocation for the device data) and initializes the
12262306a36Sopenharmony_civirtqueue. virtio_device_ready() is used to enable the virtqueue and to
12362306a36Sopenharmony_cinotify the device that the driver is ready to manage the device
12462306a36Sopenharmony_ci("DRIVER_OK"). The virtqueues are anyway enabled automatically by the
12562306a36Sopenharmony_cicore after ``probe`` returns.
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci.. kernel-doc:: include/linux/virtio_config.h
12862306a36Sopenharmony_ci    :identifiers: virtio_device_ready
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ciIn any case, the virtqueues need to be enabled before adding buffers to
13162306a36Sopenharmony_cithem.
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ciSending and receiving data
13462306a36Sopenharmony_ci==========================
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciThe virtio_dummy_recv_cb() callback in the code above will be triggered
13762306a36Sopenharmony_ciwhen the device notifies the driver after it finishes processing a
13862306a36Sopenharmony_cidescriptor or descriptor chain, either for reading or writing. However,
13962306a36Sopenharmony_cithat's only the second half of the virtio device-driver communication
14062306a36Sopenharmony_ciprocess, as the communication is always started by the driver regardless
14162306a36Sopenharmony_ciof the direction of the data transfer.
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ciTo configure a buffer transfer from the driver to the device, first you
14462306a36Sopenharmony_cihave to add the buffers -- packed as `scatterlists` -- to the
14562306a36Sopenharmony_ciappropriate virtqueue using any of the virtqueue_add_inbuf(),
14662306a36Sopenharmony_civirtqueue_add_outbuf() or virtqueue_add_sgs(), depending on whether you
14762306a36Sopenharmony_cineed to add one input `scatterlist` (for the device to fill in), one
14862306a36Sopenharmony_cioutput `scatterlist` (for the device to consume) or multiple
14962306a36Sopenharmony_ci`scatterlists`, respectively. Then, once the virtqueue is set up, a call
15062306a36Sopenharmony_cito virtqueue_kick() sends a notification that will be serviced by the
15162306a36Sopenharmony_cihypervisor that implements the device::
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	struct scatterlist sg[1];
15462306a36Sopenharmony_ci	sg_init_one(sg, buffer, BUFLEN);
15562306a36Sopenharmony_ci	virtqueue_add_inbuf(dev->vq, sg, 1, buffer, GFP_ATOMIC);
15662306a36Sopenharmony_ci	virtqueue_kick(dev->vq);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c
15962306a36Sopenharmony_ci    :identifiers: virtqueue_add_inbuf
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c
16262306a36Sopenharmony_ci    :identifiers: virtqueue_add_outbuf
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c
16562306a36Sopenharmony_ci    :identifiers: virtqueue_add_sgs
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ciThen, after the device has read or written the buffers prepared by the
16862306a36Sopenharmony_cidriver and notifies it back, the driver can call virtqueue_get_buf() to
16962306a36Sopenharmony_ciread the data produced by the device (if the virtqueue was set up with
17062306a36Sopenharmony_ciinput buffers) or simply to reclaim the buffers if they were already
17162306a36Sopenharmony_ciconsumed by the device:
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c
17462306a36Sopenharmony_ci    :identifiers: virtqueue_get_buf_ctx
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ciThe virtqueue callbacks can be disabled and re-enabled using the
17762306a36Sopenharmony_civirtqueue_disable_cb() and the family of virtqueue_enable_cb() functions
17862306a36Sopenharmony_cirespectively. See drivers/virtio/virtio_ring.c for more details:
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c
18162306a36Sopenharmony_ci    :identifiers: virtqueue_disable_cb
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c
18462306a36Sopenharmony_ci    :identifiers: virtqueue_enable_cb
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciBut note that some spurious callbacks can still be triggered under
18762306a36Sopenharmony_cicertain scenarios. The way to disable callbacks reliably is to reset the
18862306a36Sopenharmony_cidevice or the virtqueue (virtio_reset_device()).
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ciReferences
19262306a36Sopenharmony_ci==========
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci_`[1]` Virtio Spec v1.2:
19562306a36Sopenharmony_cihttps://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ciCheck for later versions of the spec as well.
198