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