diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-02-05 17:06:20 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-08 18:13:10 +0200 |
commit | 0d09e41a51aa0752b1ce525ce084f7cd210e461b (patch) | |
tree | dc92b5b32c1e3182afa9bfd16a46a0a089320102 /include/hw/virtio | |
parent | bb585a784e9ad69207315d694e7dad2c422f6baa (diff) |
hw: move headers to include/
Many of these should be cleaned up with proper qdev-/QOM-ification.
Right now there are many catch-all headers in include/hw/ARCH depending
on cpu.h, and this makes it necessary to compile these files per-target.
However, fixing this does not belong in these patches.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include/hw/virtio')
-rw-r--r-- | include/hw/virtio/dataplane/hostmem.h | 57 | ||||
-rw-r--r-- | include/hw/virtio/dataplane/vring.h | 62 | ||||
-rw-r--r-- | include/hw/virtio/vhost.h | 68 | ||||
-rw-r--r-- | include/hw/virtio/virtio-9p.h | 24 | ||||
-rw-r--r-- | include/hw/virtio/virtio-balloon.h | 72 | ||||
-rw-r--r-- | include/hw/virtio/virtio-blk.h | 152 | ||||
-rw-r--r-- | include/hw/virtio/virtio-bus.h | 94 | ||||
-rw-r--r-- | include/hw/virtio/virtio-net.h | 246 | ||||
-rw-r--r-- | include/hw/virtio/virtio-rng.h | 47 | ||||
-rw-r--r-- | include/hw/virtio/virtio-scsi.h | 66 | ||||
-rw-r--r-- | include/hw/virtio/virtio-serial.h | 247 | ||||
-rw-r--r-- | include/hw/virtio/virtio.h | 292 |
12 files changed, 1427 insertions, 0 deletions
diff --git a/include/hw/virtio/dataplane/hostmem.h b/include/hw/virtio/dataplane/hostmem.h new file mode 100644 index 0000000000..b2cf09333f --- /dev/null +++ b/include/hw/virtio/dataplane/hostmem.h @@ -0,0 +1,57 @@ +/* + * Thread-safe guest to host memory mapping + * + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi <stefanha@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef HOSTMEM_H +#define HOSTMEM_H + +#include "exec/memory.h" +#include "qemu/thread.h" + +typedef struct { + void *host_addr; + hwaddr guest_addr; + uint64_t size; + bool readonly; +} HostMemRegion; + +typedef struct { + /* The listener is invoked when regions change and a new list of regions is + * built up completely before they are installed. + */ + MemoryListener listener; + HostMemRegion *new_regions; + size_t num_new_regions; + + /* Current regions are accessed from multiple threads either to lookup + * addresses or to install a new list of regions. The lock protects the + * pointer and the regions. + */ + QemuMutex current_regions_lock; + HostMemRegion *current_regions; + size_t num_current_regions; +} HostMem; + +void hostmem_init(HostMem *hostmem); +void hostmem_finalize(HostMem *hostmem); + +/** + * Map a guest physical address to a pointer + * + * Note that there is map/unmap mechanism here. The caller must ensure that + * mapped memory is no longer used across events like hot memory unplug. This + * can be done with other mechanisms like bdrv_drain_all() that quiesce + * in-flight I/O. + */ +void *hostmem_lookup(HostMem *hostmem, hwaddr phys, hwaddr len, bool is_write); + +#endif /* HOSTMEM_H */ diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h new file mode 100644 index 0000000000..9380cb5413 --- /dev/null +++ b/include/hw/virtio/dataplane/vring.h @@ -0,0 +1,62 @@ +/* Copyright 2012 Red Hat, Inc. and/or its affiliates + * Copyright IBM, Corp. 2012 + * + * Based on Linux 2.6.39 vhost code: + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin <mst@redhat.com> + * Stefan Hajnoczi <stefanha@redhat.com> + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * This work is licensed under the terms of the GNU GPL, version 2. + */ + +#ifndef VRING_H +#define VRING_H + +#include <linux/virtio_ring.h> +#include "qemu-common.h" +#include "hostmem.h" +#include "hw/virtio/virtio.h" + +typedef struct { + HostMem hostmem; /* guest memory mapper */ + struct vring vr; /* virtqueue vring mapped to host memory */ + uint16_t last_avail_idx; /* last processed avail ring index */ + uint16_t last_used_idx; /* last processed used ring index */ + uint16_t signalled_used; /* EVENT_IDX state */ + bool signalled_used_valid; + bool broken; /* was there a fatal error? */ +} Vring; + +static inline unsigned int vring_get_num(Vring *vring) +{ + return vring->vr.num; +} + +/* Are there more descriptors available? */ +static inline bool vring_more_avail(Vring *vring) +{ + return vring->vr.avail->idx != vring->last_avail_idx; +} + +/* Fail future vring_pop() and vring_push() calls until reset */ +static inline void vring_set_broken(Vring *vring) +{ + vring->broken = true; +} + +bool vring_setup(Vring *vring, VirtIODevice *vdev, int n); +void vring_teardown(Vring *vring); +void vring_disable_notification(VirtIODevice *vdev, Vring *vring); +bool vring_enable_notification(VirtIODevice *vdev, Vring *vring); +bool vring_should_notify(VirtIODevice *vdev, Vring *vring); +int vring_pop(VirtIODevice *vdev, Vring *vring, + struct iovec iov[], struct iovec *iov_end, + unsigned int *out_num, unsigned int *in_num); +void vring_push(Vring *vring, unsigned int head, int len); + +#endif /* VRING_H */ diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h new file mode 100644 index 0000000000..b373be0387 --- /dev/null +++ b/include/hw/virtio/vhost.h @@ -0,0 +1,68 @@ +#ifndef VHOST_H +#define VHOST_H + +#include "hw/hw.h" +#include "hw/virtio/virtio.h" +#include "exec/memory.h" + +/* Generic structures common for any vhost based device. */ +struct vhost_virtqueue { + int kick; + int call; + void *desc; + void *avail; + void *used; + int num; + unsigned long long used_phys; + unsigned used_size; + void *ring; + unsigned long long ring_phys; + unsigned ring_size; + EventNotifier masked_notifier; +}; + +typedef unsigned long vhost_log_chunk_t; +#define VHOST_LOG_PAGE 0x1000 +#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) +#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) + +struct vhost_memory; +struct vhost_dev { + MemoryListener memory_listener; + int control; + struct vhost_memory *mem; + int n_mem_sections; + MemoryRegionSection *mem_sections; + struct vhost_virtqueue *vqs; + int nvqs; + /* the first virtuque which would be used by this vhost dev */ + int vq_index; + unsigned long long features; + unsigned long long acked_features; + unsigned long long backend_features; + bool started; + bool log_enabled; + vhost_log_chunk_t *log; + unsigned long long log_size; + bool force; +}; + +int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, + bool force); +void vhost_dev_cleanup(struct vhost_dev *hdev); +bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); +void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + +/* Test and clear masked event pending status. + * Should be called after unmask to avoid losing events. + */ +bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n); + +/* Mask/unmask events from this vq. + */ +void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, + bool mask); +#endif diff --git a/include/hw/virtio/virtio-9p.h b/include/hw/virtio/virtio-9p.h new file mode 100644 index 0000000000..65789db131 --- /dev/null +++ b/include/hw/virtio/virtio-9p.h @@ -0,0 +1,24 @@ +/* + * Virtio 9p + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> + * + * 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_9P_DEVICE_H +#define QEMU_VIRTIO_9P_DEVICE_H + +typedef struct V9fsConf +{ + /* tag name for the device */ + char *tag; + char *fsdev_id; +} V9fsConf; + +#endif diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h new file mode 100644 index 0000000000..3b459bbdd7 --- /dev/null +++ b/include/hw/virtio/virtio-balloon.h @@ -0,0 +1,72 @@ +/* + * Virtio Support + * + * Copyright IBM, Corp. 2007-2008 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * Rusty Russell <rusty@rustcorp.com.au> + * + * 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_BALLOON_H +#define _QEMU_VIRTIO_BALLOON_H + +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#define TYPE_VIRTIO_BALLOON "virtio-balloon" +#define VIRTIO_BALLOON(obj) \ + OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON) + +/* from Linux's linux/virtio_balloon.h */ + +/* The ID for virtio_balloon */ +#define VIRTIO_ID_BALLOON 5 + +/* The feature bitmap for virtio balloon */ +#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ +#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory stats virtqueue */ + +/* Size of a PFN in the balloon interface. */ +#define VIRTIO_BALLOON_PFN_SHIFT 12 + +struct virtio_balloon_config +{ + /* Number of pages host wants Guest to give up. */ + uint32_t num_pages; + /* Number of pages we've actually got in balloon. */ + uint32_t actual; +}; + +/* Memory Statistics */ +#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */ +#define VIRTIO_BALLOON_S_SWAP_OUT 1 /* Amount of memory swapped out */ +#define VIRTIO_BALLOON_S_MAJFLT 2 /* Number of major faults */ +#define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ +#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ +#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ +#define VIRTIO_BALLOON_S_NR 6 + +typedef struct VirtIOBalloonStat { + uint16_t tag; + uint64_t val; +} QEMU_PACKED VirtIOBalloonStat; + +typedef struct VirtIOBalloon { + VirtIODevice parent_obj; + VirtQueue *ivq, *dvq, *svq; + uint32_t num_pages; + uint32_t actual; + uint64_t stats[VIRTIO_BALLOON_S_NR]; + VirtQueueElement stats_vq_elem; + size_t stats_vq_offset; + QEMUTimer *stats_timer; + int64_t stats_last_update; + int64_t stats_poll_interval; +} VirtIOBalloon; + +#endif diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h new file mode 100644 index 0000000000..c10d069b25 --- /dev/null +++ b/include/hw/virtio/virtio-blk.h @@ -0,0 +1,152 @@ +/* + * Virtio Block Device + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * 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_BLK_H +#define _QEMU_VIRTIO_BLK_H + +#include "hw/virtio/virtio.h" +#include "hw/block/block.h" + +#define TYPE_VIRTIO_BLK "virtio-blk" +#define VIRTIO_BLK(obj) \ + OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK) + +/* from Linux's linux/virtio_blk.h */ + +/* The ID for virtio_block */ +#define VIRTIO_ID_BLOCK 2 + +/* Feature bits */ +#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ +#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ +#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ +#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */ +#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ +#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ +#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ +/* #define VIRTIO_BLK_F_IDENTIFY 8 ATA IDENTIFY supported, DEPRECATED */ +#define VIRTIO_BLK_F_WCE 9 /* write cache enabled */ +#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ +#define VIRTIO_BLK_F_CONFIG_WCE 11 /* write cache configurable */ + +#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ + +struct virtio_blk_config +{ + uint64_t capacity; + uint32_t size_max; + uint32_t seg_max; + uint16_t cylinders; + uint8_t heads; + uint8_t sectors; + uint32_t blk_size; + uint8_t physical_block_exp; + uint8_t alignment_offset; + uint16_t min_io_size; + uint32_t opt_io_size; + uint8_t wce; +} QEMU_PACKED; + +/* These two define direction. */ +#define VIRTIO_BLK_T_IN 0 +#define VIRTIO_BLK_T_OUT 1 + +/* This bit says it's a scsi command, not an actual read or write. */ +#define VIRTIO_BLK_T_SCSI_CMD 2 + +/* Flush the volatile write cache */ +#define VIRTIO_BLK_T_FLUSH 4 + +/* return the device ID string */ +#define VIRTIO_BLK_T_GET_ID 8 + +/* Barrier before this op. */ +#define VIRTIO_BLK_T_BARRIER 0x80000000 + +/* This is the first element of the read scatter-gather list. */ +struct virtio_blk_outhdr +{ + /* VIRTIO_BLK_T* */ + uint32_t type; + /* io priority. */ + uint32_t ioprio; + /* Sector (ie. 512 byte offset) */ + uint64_t sector; +}; + +#define VIRTIO_BLK_S_OK 0 +#define VIRTIO_BLK_S_IOERR 1 +#define VIRTIO_BLK_S_UNSUPP 2 + +/* This is the last element of the write scatter-gather list */ +struct virtio_blk_inhdr +{ + unsigned char status; +}; + +/* SCSI pass-through header */ +struct virtio_scsi_inhdr +{ + uint32_t errors; + uint32_t data_len; + uint32_t sense_len; + uint32_t residual; +}; + +struct VirtIOBlkConf +{ + BlockConf conf; + char *serial; + uint32_t scsi; + uint32_t config_wce; + uint32_t data_plane; +}; + +struct VirtIOBlockDataPlane; + +typedef struct VirtIOBlock { + VirtIODevice parent_obj; + BlockDriverState *bs; + VirtQueue *vq; + void *rq; + QEMUBH *bh; + BlockConf *conf; + VirtIOBlkConf blk; + unsigned short sector_mask; + VMChangeStateEntry *change; +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + struct VirtIOBlockDataPlane *dataplane; +#endif +} VirtIOBlock; + +#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) + +#ifdef __linux__ +#define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field) \ + DEFINE_BLOCK_PROPERTIES(_state, _field.conf), \ + DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf), \ + DEFINE_PROP_STRING("serial", _state, _field.serial), \ + DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true), \ + DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true) +#else +#define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field) \ + DEFINE_BLOCK_PROPERTIES(_state, _field.conf), \ + DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf), \ + DEFINE_PROP_STRING("serial", _state, _field.serial), \ + DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true) +#endif /* __linux__ */ + +void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk); + +#endif diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h new file mode 100644 index 0000000000..311e8c78bd --- /dev/null +++ b/include/hw/virtio/virtio-bus.h @@ -0,0 +1,94 @@ +/* + * VirtioBus + * + * Copyright (C) 2012 : GreenSocs Ltd + * http://www.greensocs.com/ , email: info@greensocs.com + * + * Developed by : + * Frederic Konrad <fred.konrad@greensocs.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef VIRTIO_BUS_H +#define VIRTIO_BUS_H + +#include "hw/qdev.h" +#include "sysemu/sysemu.h" +#include "hw/virtio/virtio.h" + +#define TYPE_VIRTIO_BUS "virtio-bus" +#define VIRTIO_BUS_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS) +#define VIRTIO_BUS_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS) +#define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS) + +typedef struct VirtioBusState VirtioBusState; + +typedef struct VirtioBusClass { + /* This is what a VirtioBus must implement */ + BusClass parent; + void (*notify)(DeviceState *d, uint16_t vector); + void (*save_config)(DeviceState *d, QEMUFile *f); + void (*save_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_config)(DeviceState *d, QEMUFile *f); + int (*load_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_done)(DeviceState *d, QEMUFile *f); + unsigned (*get_features)(DeviceState *d); + bool (*query_guest_notifiers)(DeviceState *d); + int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign); + int (*set_host_notifier)(DeviceState *d, int n, bool assigned); + void (*vmstate_change)(DeviceState *d, bool running); + /* + * transport independent init function. + * This is called by virtio-bus just after the device is plugged. + */ + void (*device_plugged)(DeviceState *d); + /* + * transport independent exit function. + * This is called by virtio-bus just before the device is unplugged. + */ + void (*device_unplug)(DeviceState *d); +} VirtioBusClass; + +struct VirtioBusState { + BusState parent_obj; + /* + * Only one VirtIODevice can be plugged on the bus. + */ + VirtIODevice *vdev; + /* + * This will be removed at the end of the series. + */ + VirtIOBindings bindings; +}; + +int virtio_bus_plug_device(VirtIODevice *vdev); +void virtio_bus_reset(VirtioBusState *bus); +void virtio_bus_destroy_device(VirtioBusState *bus); +/* Get the device id of the plugged device. */ +uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus); +/* Get the config_len field of the plugged device. */ +size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); +/* Get the features of the plugged device. */ +uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, + uint32_t requested_features); +/* Get bad features of the plugged device. */ +uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); +/* Get config of the plugged device. */ +void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config); + +#endif /* VIRTIO_BUS_H */ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h new file mode 100644 index 0000000000..d2cc996872 --- /dev/null +++ b/include/hw/virtio/virtio-net.h @@ -0,0 +1,246 @@ +/* + * Virtio Network Device + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * 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_NET_H +#define _QEMU_VIRTIO_NET_H + +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#define ETH_ALEN 6 + +/* from Linux's virtio_net.h */ + +/* The ID for virtio_net */ +#define VIRTIO_ID_NET 1 + +/* The feature bitmap for virtio net */ +#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ +#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ +#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ +#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ +#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ +#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ +#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ +#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ +#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ +#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ +#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ +#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow + * Steering */ + +#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ + +#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ + +#define TX_TIMER_INTERVAL 150000 /* 150 us */ + +/* Limit the number of packets that can be sent via a single flush + * of the TX queue. This gives us a guaranteed exit condition and + * ensures fairness in the io path. 256 conveniently matches the + * length of the TX queue and shows a good balance of performance + * and latency. */ +#define TX_BURST 256 + +typedef struct virtio_net_conf +{ + uint32_t txtimer; + int32_t txburst; + char *tx; +} virtio_net_conf; + +/* Maximum packet size we can receive from tap device: header + 64k */ +#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10)) + +struct virtio_net_config +{ + /* The config defining mac address ($ETH_ALEN bytes) */ + uint8_t mac[ETH_ALEN]; + /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ + uint16_t status; + /* Max virtqueue pairs supported by the device */ + uint16_t max_virtqueue_pairs; +} QEMU_PACKED; + +/* + * Control virtqueue data structures + * + * The control virtqueue expects a header in the first sg entry + * and an ack/status response in the last entry. Data for the + * command goes in between. + */ +struct virtio_net_ctrl_hdr { + uint8_t class; + uint8_t cmd; +}; + +typedef uint8_t virtio_net_ctrl_ack; + +#define VIRTIO_NET_OK 0 +#define VIRTIO_NET_ERR 1 + +/* + * Control the RX mode, ie. promisucous, allmulti, etc... + * All commands require an "out" sg entry containing a 1 byte + * state value, zero = disable, non-zero = enable. Commands + * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. + * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. + */ +#define VIRTIO_NET_CTRL_RX 0 + #define VIRTIO_NET_CTRL_RX_PROMISC 0 + #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 + #define VIRTIO_NET_CTRL_RX_ALLUNI 2 + #define VIRTIO_NET_CTRL_RX_NOMULTI 3 + #define VIRTIO_NET_CTRL_RX_NOUNI 4 + #define VIRTIO_NET_CTRL_RX_NOBCAST 5 + +/* + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + uint32_t entries; + uint8_t macs[][ETH_ALEN]; +}; + +typedef struct VirtIONetQueue { + VirtQueue *rx_vq; + VirtQueue *tx_vq; + QEMUTimer *tx_timer; + QEMUBH *tx_bh; + int tx_waiting; + struct { + VirtQueueElement elem; + ssize_t len; + } async_tx; + struct VirtIONet *n; +} VirtIONetQueue; + +typedef struct VirtIONet { + VirtIODevice vdev; + uint8_t mac[ETH_ALEN]; + uint16_t status; + VirtIONetQueue *vqs; + VirtQueue *ctrl_vq; + NICState *nic; + uint32_t tx_timeout; + int32_t tx_burst; + uint32_t has_vnet_hdr; + size_t host_hdr_len; + size_t guest_hdr_len; + uint8_t has_ufo; + int mergeable_rx_bufs; + uint8_t promisc; + uint8_t allmulti; + uint8_t alluni; + uint8_t nomulti; + uint8_t nouni; + uint8_t nobcast; + uint8_t vhost_started; + struct { + int in_use; + int first_multi; + uint8_t multi_overflow; + uint8_t uni_overflow; + uint8_t *macs; + } mac_table; + uint32_t *vlans; + DeviceState *qdev; + int multiqueue; + uint16_t max_queues; + uint16_t curr_queues; + size_t config_size; +} VirtIONet; + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/* + * Control VLAN filtering + * + * The VLAN filter table is controlled via a simple ADD/DEL interface. + * VLAN IDs not added may be filterd by the hypervisor. Del is the + * opposite of add. Both commands expect an out entry containing a 2 + * byte VLAN ID. VLAN filterting is available with the + * VIRTIO_NET_F_CTRL_VLAN feature bit. + */ +#define VIRTIO_NET_CTRL_VLAN 2 + #define VIRTIO_NET_CTRL_VLAN_ADD 0 + #define VIRTIO_NET_CTRL_VLAN_DEL 1 + +/* + * Control Multiqueue + * + * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET + * enables multiqueue, specifying the number of the transmit and + * receive queues that will be used. After the command is consumed and acked by + * the device, the device will not steer new packets on receive virtqueues + * other than specified nor read from transmit virtqueues other than specified. + * Accordingly, driver should not transmit new packets on virtqueues other than + * specified. + */ +struct virtio_net_ctrl_mq { + uint16_t virtqueue_pairs; +}; + +#define VIRTIO_NET_CTRL_MQ 4 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 + +#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ + DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \ + DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \ + DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \ + DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \ + DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \ + DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \ + DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \ + DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \ + DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \ + DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \ + DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \ + DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \ + DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \ + DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \ + DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ + DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \ + DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \ + DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false) + +#endif diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h new file mode 100644 index 0000000000..3711c97a70 --- /dev/null +++ b/include/hw/virtio/virtio-rng.h @@ -0,0 +1,47 @@ +/* + * Virtio RNG Support + * + * Copyright Red Hat, Inc. 2012 + * Copyright Amit Shah <amit.shah@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#ifndef _QEMU_VIRTIO_RNG_H +#define _QEMU_VIRTIO_RNG_H + +#include "qemu/rng.h" +#include "qemu/rng-random.h" + +/* The Virtio ID for the virtio rng device */ +#define VIRTIO_ID_RNG 4 + +struct VirtIORNGConf { + RngBackend *rng; + uint64_t max_bytes; + uint32_t period_ms; + RndRandom *default_backend; +}; + +typedef struct VirtIORNG { + VirtIODevice vdev; + + DeviceState *qdev; + + /* Only one vq - guest puts buffer(s) on it when it needs entropy */ + VirtQueue *vq; + + VirtIORNGConf *conf; + + RngBackend *rng; + + /* We purposefully don't migrate this state. The quota will reset on the + * destination as a result. Rate limiting is host state, not guest state. + */ + QEMUTimer *rate_limit_timer; + int64_t quota_remaining; +} VirtIORNG; + +#endif diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h new file mode 100644 index 0000000000..c9d92ca2e8 --- /dev/null +++ b/include/hw/virtio/virtio-scsi.h @@ -0,0 +1,66 @@ +/* + * Virtio SCSI HBA + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> + * + * 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_SCSI_H +#define _QEMU_VIRTIO_SCSI_H + +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" +#include "hw/scsi/scsi.h" + +#define TYPE_VIRTIO_SCSI "virtio-scsi" +#define VIRTIO_SCSI(obj) \ + OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) + + +/* The ID for virtio_scsi */ +#define VIRTIO_ID_SCSI 8 + +/* Feature Bits */ +#define VIRTIO_SCSI_F_INOUT 0 +#define VIRTIO_SCSI_F_HOTPLUG 1 +#define VIRTIO_SCSI_F_CHANGE 2 + +struct VirtIOSCSIConf { + uint32_t num_queues; + uint32_t max_sectors; + uint32_t cmd_per_lun; +}; + +typedef struct VirtIOSCSI { + VirtIODevice parent_obj; + VirtIOSCSIConf conf; + + SCSIBus bus; + uint32_t sense_size; + uint32_t cdb_size; + int resetting; + bool events_dropped; + VirtQueue *ctrl_vq; + VirtQueue *event_vq; + VirtQueue **cmd_vqs; +} VirtIOSCSI; + +#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field) \ + DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ + DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\ + DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) + +#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _feature_field), \ + DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \ + true), \ + DEFINE_PROP_BIT("param_change", _state, _feature_field, \ + VIRTIO_SCSI_F_CHANGE, true) + +#endif /* _QEMU_VIRTIO_SCSI_H */ diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h new file mode 100644 index 0000000000..098deeac4a --- /dev/null +++ b/include/hw/virtio/virtio-serial.h @@ -0,0 +1,247 @@ +/* + * Virtio Serial / Console Support + * + * Copyright IBM, Corp. 2008 + * Copyright Red Hat, Inc. 2009, 2010 + * + * Authors: + * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> + * Amit Shah <amit.shah@redhat.com> + * + * 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_SERIAL_H +#define _QEMU_VIRTIO_SERIAL_H + +#include "hw/qdev.h" +#include "hw/virtio/virtio.h" + +/* == Interface shared between the guest kernel and qemu == */ + +/* The Virtio ID for virtio console / serial ports */ +#define VIRTIO_ID_CONSOLE 3 + +/* Features supported */ +#define VIRTIO_CONSOLE_F_MULTIPORT 1 + +#define VIRTIO_CONSOLE_BAD_ID (~(uint32_t)0) + +struct virtio_console_config { + /* + * These two fields are used by VIRTIO_CONSOLE_F_SIZE which + * isn't implemented here yet + */ + uint16_t cols; + uint16_t rows; + + uint32_t max_nr_ports; +} QEMU_PACKED; + +struct virtio_console_control { + uint32_t id; /* Port number */ + uint16_t event; /* The kind of control event (see below) */ + uint16_t value; /* Extra information for the key */ +}; + +struct virtio_serial_conf { + /* Max. number of ports we can have for a virtio-serial device */ + uint32_t max_virtserial_ports; +}; + +/* Some events for the internal messages (control packets) */ +#define VIRTIO_CONSOLE_DEVICE_READY 0 +#define VIRTIO_CONSOLE_PORT_ADD 1 +#define VIRTIO_CONSOLE_PORT_REMOVE 2 +#define VIRTIO_CONSOLE_PORT_READY 3 +#define VIRTIO_CONSOLE_CONSOLE_PORT 4 +#define VIRTIO_CONSOLE_RESIZE 5 +#define VIRTIO_CONSOLE_PORT_OPEN 6 +#define VIRTIO_CONSOLE_PORT_NAME 7 + +/* == In-qemu interface == */ + +#define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port" +#define VIRTIO_SERIAL_PORT(obj) \ + OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT) +#define VIRTIO_SERIAL_PORT_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtIOSerialPortClass, (klass), TYPE_VIRTIO_SERIAL_PORT) +#define VIRTIO_SERIAL_PORT_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtIOSerialPortClass, (obj), TYPE_VIRTIO_SERIAL_PORT) + +typedef struct VirtIOSerial VirtIOSerial; +typedef struct VirtIOSerialBus VirtIOSerialBus; +typedef struct VirtIOSerialPort VirtIOSerialPort; + +typedef struct VirtIOSerialPortClass { + DeviceClass parent_class; + + /* Is this a device that binds with hvc in the guest? */ + bool is_console; + + /* + * The per-port (or per-app) init function that's called when a + * new device is found on the bus. + */ + int (*init)(VirtIOSerialPort *port); + /* + * Per-port exit function that's called when a port gets + * hot-unplugged or removed. + */ + int (*exit)(VirtIOSerialPort *port); + + /* Callbacks for guest events */ + /* Guest opened/closed device. */ + void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected); + + /* Guest is now ready to accept data (virtqueues set up). */ + void (*guest_ready)(VirtIOSerialPort *port); + + /* + * Guest wrote some data to the port. This data is handed over to + * the app via this callback. The app can return a size less than + * 'len'. In this case, throttling will be enabled for this port. + */ + ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, + size_t len); +} VirtIOSerialPortClass; + +/* + * This is the state that's shared between all the ports. Some of the + * state is configurable via command-line options. Some of it can be + * set by individual devices in their initfn routines. Some of the + * state is set by the generic qdev device init routine. + */ +struct VirtIOSerialPort { + DeviceState dev; + + QTAILQ_ENTRY(VirtIOSerialPort) next; + + /* + * This field gives us the virtio device as well as the qdev bus + * that we are associated with + */ + VirtIOSerial *vser; + + VirtQueue *ivq, *ovq; + + /* + * This name is sent to the guest and exported via sysfs. + * The guest could create symlinks based on this information. + * The name is in the reverse fqdn format, like org.qemu.console.0 + */ + char *name; + + /* + * This id helps identify ports between the guest and the host. + * The guest sends a "header" with this id with each data packet + * that it sends and the host can then find out which associated + * device to send out this data to + */ + uint32_t id; + + /* + * This is the elem that we pop from the virtqueue. A slow + * backend that consumes guest data (e.g. the file backend for + * qemu chardevs) can cause the guest to block till all the output + * is flushed. This isn't desired, so we keep a note of the last + * element popped and continue consuming it once the backend + * becomes writable again. + */ + VirtQueueElement elem; + + /* + * The index and the offset into the iov buffer that was popped in + * elem above. + */ + uint32_t iov_idx; + uint64_t iov_offset; + + /* + * When unthrottling we use a bottom-half to call flush_queued_data. + */ + QEMUBH *bh; + + /* Is the corresponding guest device open? */ + bool guest_connected; + /* Is this device open for IO on the host? */ + bool host_connected; + /* Do apps not want to receive data? */ + bool throttled; +}; + +/* The virtio-serial bus on top of which the ports will ride as devices */ +struct VirtIOSerialBus { + BusState qbus; + + /* This is the parent device that provides the bus for ports. */ + VirtIOSerial *vser; + + /* The maximum number of ports that can ride on top of this bus */ + uint32_t max_nr_ports; +}; + +typedef struct VirtIOSerialPostLoad { + QEMUTimer *timer; + uint32_t nr_active_ports; + struct { + VirtIOSerialPort *port; + uint8_t host_connected; + } *connected; +} VirtIOSerialPostLoad; + +struct VirtIOSerial { + VirtIODevice vdev; + + VirtQueue *c_ivq, *c_ovq; + /* Arrays of ivqs and ovqs: one per port */ + VirtQueue **ivqs, **ovqs; + + VirtIOSerialBus bus; + + DeviceState *qdev; + + QTAILQ_HEAD(, VirtIOSerialPort) ports; + + /* bitmap for identifying active ports */ + uint32_t *ports_map; + + struct virtio_console_config config; + + struct VirtIOSerialPostLoad *post_load; +}; + +/* Interface to the virtio-serial bus */ + +/* + * Open a connection to the port + * Returns 0 on success (always). + */ +int virtio_serial_open(VirtIOSerialPort *port); + +/* + * Close the connection to the port + * Returns 0 on success (always). + */ +int virtio_serial_close(VirtIOSerialPort *port); + +/* + * Send data to Guest + */ +ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf, + size_t size); + +/* + * Query whether a guest is ready to receive data. + */ +size_t virtio_serial_guest_ready(VirtIOSerialPort *port); + +/* + * Flow control: Ports can signal to the virtio-serial core to stop + * sending data or re-start sending data, depending on the 'throttle' + * value here. + */ +void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); + +#endif diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h new file mode 100644 index 0000000000..7e24b2b69a --- /dev/null +++ b/include/hw/virtio/virtio.h @@ -0,0 +1,292 @@ +/* + * Virtio Support + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * 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 "hw/hw.h" +#include "net/net.h" +#include "hw/qdev.h" +#include "sysemu/sysemu.h" +#include "qemu/event_notifier.h" +#ifdef CONFIG_VIRTFS +#include "hw/virtio/virtio-9p.h" +#endif + +/* 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 + +/* Some virtio feature bits (currently bits 28 through 31) are reserved for the + * transport being used (eg. virtio_ring), the rest are per-device feature bits. */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 32 + +/* We notify when the ring is completely used, even if the guest is suppressing + * callbacks */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 +/* We support indirect buffer descriptors */ +#define VIRTIO_RING_F_INDIRECT_DESC 28 +/* The Guest publishes the used index for which it expects an interrupt + * at the end of the avail ring. Host should ignore the avail->flags field. */ +/* The Host publishes the avail index for which it expects a kick + * at the end of the used ring. Guest should ignore the used->flags field. */ +#define VIRTIO_RING_F_EVENT_IDX 29 +/* A guest should never accept this. It implies negotiation is broken. */ +#define VIRTIO_F_BAD_FEATURE 30 + +/* 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 the buffer contains a list of buffer descriptors. */ +#define VRING_DESC_F_INDIRECT 4 + +/* 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; + +static inline hwaddr vring_align(hwaddr addr, + unsigned long align) +{ + return (addr + align - 1) & ~(align - 1); +} + +typedef struct VirtQueue VirtQueue; + +#define VIRTQUEUE_MAX_SIZE 1024 + +typedef struct VirtQueueElement +{ + unsigned int index; + unsigned int out_num; + unsigned int in_num; + hwaddr in_addr[VIRTQUEUE_MAX_SIZE]; + hwaddr out_addr[VIRTQUEUE_MAX_SIZE]; + struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; + struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; +} VirtQueueElement; + +typedef struct { + void (*notify)(DeviceState *d, uint16_t vector); + void (*save_config)(DeviceState *d, QEMUFile *f); + void (*save_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_config)(DeviceState *d, QEMUFile *f); + int (*load_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_done)(DeviceState *d, QEMUFile *f); + unsigned (*get_features)(DeviceState *d); + bool (*query_guest_notifiers)(DeviceState *d); + int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assigned); + int (*set_host_notifier)(DeviceState *d, int n, bool assigned); + void (*vmstate_change)(DeviceState *d, bool running); +} VirtIOBindings; + +#define VIRTIO_PCI_QUEUE_MAX 64 + +#define VIRTIO_NO_VECTOR 0xffff + +#define TYPE_VIRTIO_DEVICE "virtio-device" +#define VIRTIO_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_VIRTIO_DEVICE) +#define VIRTIO_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_VIRTIO_DEVICE) +#define VIRTIO_DEVICE(obj) \ + OBJECT_CHECK(VirtIODevice, (obj), TYPE_VIRTIO_DEVICE) + +struct VirtIODevice +{ + DeviceState parent_obj; + const char *name; + uint8_t status; + uint8_t isr; + uint16_t queue_sel; + uint32_t guest_features; + size_t config_len; + void *config; + uint16_t config_vector; + int nvectors; + /* + * Function pointers will be removed at the end of the series as they are in + * VirtioDeviceClass. + */ + uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features); + uint32_t (*bad_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); + void (*set_status)(VirtIODevice *vdev, uint8_t val); + /* Test and clear event pending status. + * Should be called after unmask to avoid losing events. + * If backend does not support masking, + * must check in frontend instead. + */ + bool (*guest_notifier_pending)(VirtIODevice *vdev, int n); + /* Mask/unmask events from this vq. Any events reported + * while masked will become pending. + * If backend does not support masking, + * must mask in frontend instead. + */ + void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask); + + VirtQueue *vq; + const VirtIOBindings *binding; + DeviceState *binding_opaque; + uint16_t device_id; + bool vm_running; + VMChangeStateEntry *vmstate; +}; + +typedef struct VirtioDeviceClass { + /* This is what a VirtioDevice must implement */ + DeviceClass parent; + int (*init)(VirtIODevice *vdev); + uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features); + uint32_t (*bad_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); + void (*set_status)(VirtIODevice *vdev, uint8_t val); +} VirtioDeviceClass; + +void virtio_init(VirtIODevice *vdev, const char *name, + uint16_t device_id, size_t config_size); +void virtio_common_cleanup(VirtIODevice *vdev); + +VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, + void (*handle_output)(VirtIODevice *, + VirtQueue *)); + +void virtio_del_queue(VirtIODevice *vdev, int n); + +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); + +void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, + size_t num_sg, int is_write); +int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem); +int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, + unsigned int out_bytes); +void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, + unsigned int *out_bytes, + unsigned max_in_bytes, unsigned max_out_bytes); + +void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); + +void virtio_save(VirtIODevice *vdev, QEMUFile *f); + +int virtio_load(VirtIODevice *vdev, QEMUFile *f); + +void virtio_cleanup(VirtIODevice *vdev); + +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); + +/* Host binding interface. */ + +VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, + size_t config_size, size_t struct_size); +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); +hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); +int virtio_queue_get_num(VirtIODevice *vdev, int n); +void virtio_queue_notify(VirtIODevice *vdev, int n); +uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); +void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); +void virtio_set_status(VirtIODevice *vdev, uint8_t val); +void virtio_reset(void *opaque); +void virtio_update_irq(VirtIODevice *vdev); +int virtio_set_features(VirtIODevice *vdev, uint32_t val); + +void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, + DeviceState *opaque); + +/* Base devices. */ +typedef struct VirtIOBlkConf VirtIOBlkConf; +struct virtio_net_conf; +VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, + struct virtio_net_conf *net, + uint32_t host_features); +typedef struct virtio_serial_conf virtio_serial_conf; +VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial); +VirtIODevice *virtio_balloon_init(DeviceState *dev); +typedef struct VirtIOSCSIConf VirtIOSCSIConf; +VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf); +typedef struct VirtIORNGConf VirtIORNGConf; +VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf); +#ifdef CONFIG_VIRTFS +VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf); +#endif + + +void virtio_net_exit(VirtIODevice *vdev); +void virtio_serial_exit(VirtIODevice *vdev); +void virtio_balloon_exit(VirtIODevice *vdev); +void virtio_scsi_exit(VirtIODevice *vdev); +void virtio_rng_exit(VirtIODevice *vdev); + +#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ + DEFINE_PROP_BIT("indirect_desc", _state, _field, \ + VIRTIO_RING_F_INDIRECT_DESC, true), \ + DEFINE_PROP_BIT("event_idx", _state, _field, \ + VIRTIO_RING_F_EVENT_IDX, true) + +hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n); +uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n); +void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx); +VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n); +uint16_t virtio_get_queue_index(VirtQueue *vq); +int virtio_queue_get_id(VirtQueue *vq); +EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); +void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + bool with_irqfd); +EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); +void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, + bool set_handler); +void virtio_queue_notify_vq(VirtQueue *vq); +void virtio_irq(VirtQueue *vq); +#endif |