From 967f97fa00b2d301584d08c614d446423c65c15a Mon Sep 17 00:00:00 2001 From: aliguori Date: Thu, 4 Dec 2008 19:38:57 +0000 Subject: Virtio core support This patch adds core support for VirtIO. VirtIO is a paravirtualization framework that has been in Linux since 2.6.21. A PCI transport has been available since 2.6.25. Network drivers are also available for Windows. Signed-off-by: Anthony Liguori git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5869 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/virtio.h | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 hw/virtio.h (limited to 'hw/virtio.h') diff --git a/hw/virtio.h b/hw/virtio.h new file mode 100644 index 0000000..f04e75f --- /dev/null +++ b/hw/virtio.h @@ -0,0 +1,121 @@ +/* + * Virtio Support + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_H +#define _QEMU_VIRTIO_H + +#include +#include "hw.h" +#include "pci.h" + +/* from Linux's linux/virtio_config.h */ + +/* Status byte for guest to report progress, and synchronize features. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +/* We notify when the ring is completely used, even if the guest is supressing + * callbacks */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 + +/* from Linux's linux/virtio_ring.h */ + +/* This marks a buffer as continuing via the next field. */ +#define VRING_DESC_F_NEXT 1 +/* This marks a buffer as write-only (otherwise read-only). */ +#define VRING_DESC_F_WRITE 2 + +/* This means don't notify other side when buffer added. */ +#define VRING_USED_F_NO_NOTIFY 1 +/* This means don't interrupt guest when buffer consumed. */ +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +struct VirtQueue; + +typedef struct VirtQueue VirtQueue; +typedef struct VirtIODevice VirtIODevice; + +#define VIRTQUEUE_MAX_SIZE 1024 + +typedef struct VirtQueueElement +{ + unsigned int index; + unsigned int out_num; + unsigned int in_num; + target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE]; + struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; + struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; +} VirtQueueElement; + +#define VIRTIO_PCI_QUEUE_MAX 16 + +struct VirtIODevice +{ + PCIDevice pci_dev; + const char *name; + uint32_t addr; + uint8_t status; + uint8_t isr; + uint16_t queue_sel; + uint32_t features; + size_t config_len; + void *config; + uint32_t (*get_features)(VirtIODevice *vdev); + void (*set_features)(VirtIODevice *vdev, uint32_t val); + void (*get_config)(VirtIODevice *vdev, uint8_t *config); + void (*set_config)(VirtIODevice *vdev, const uint8_t *config); + void (*reset)(VirtIODevice *vdev); + VirtQueue *vq; +}; + +VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name, + uint16_t vendor, uint16_t device, + uint16_t subvendor, uint16_t subdevice, + uint8_t class_code, uint8_t subclass_code, + uint8_t pif, size_t config_size, + size_t struct_size); + +VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, + void (*handle_output)(VirtIODevice *, + VirtQueue *)); + +void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len); +void virtqueue_flush(VirtQueue *vq, unsigned int count); +void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len, unsigned int idx); + +int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem); +int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes); + +void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); + +void virtio_save(VirtIODevice *vdev, QEMUFile *f); + +void virtio_load(VirtIODevice *vdev, QEMUFile *f); + +void virtio_notify_config(VirtIODevice *vdev); + +void virtio_queue_set_notification(VirtQueue *vq, int enable); + +int virtio_queue_ready(VirtQueue *vq); + +int virtio_queue_empty(VirtQueue *vq); + +#endif -- cgit v1.1