2008-12-05 03:38:57 +08:00
|
|
|
/*
|
|
|
|
* 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.h"
|
2009-10-21 21:25:35 +08:00
|
|
|
#include "net.h"
|
2009-05-18 21:51:59 +08:00
|
|
|
#include "qdev.h"
|
qdev-ify virtio-blk.
First user of the new drive property. With this patch applied host
and guest config can be specified separately, like this:
-drive if=none,id=disk1,file=/path/to/disk.img
-device virtio-blk-pci,drive=disk1
You can set any property for virtio-blk-pci now. You can set the pci
address via addr=. You can switch the device into 0.10 compat mode
using class=0x0180. As this is per device you can have one 0.10 and one
0.11 virtio block device in a single virtual machine.
Old syntax continues to work. Internally it does the same as the two
lines above though. One side effect this has is a different
initialization order, which might result in a different pci address
being assigned by default.
Long term plan here is to have this working for all block devices, i.e.
once all scsi is properly qdev-ified you will be able to do something
like this:
-drive if=none,id=sda,file=/path/to/disk.img
-device lsi,id=lsi,addr=<pciaddr>
-device scsi-disk,drive=sda,bus=lsi.0,lun=<n>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Message-Id:
2009-07-31 18:25:41 +08:00
|
|
|
#include "sysemu.h"
|
block: add topology qdev properties
Add three new qdev properties to export block topology information to
the guest. This is needed to get optimal I/O alignment for RAID arrays
or SSDs.
The options are:
- physical_block_size to specify the physical block size of the device,
this is going to increase from 512 bytes to 4096 kilobytes for many
modern storage devices
- min_io_size to specify the minimal I/O size without performance impact,
this is typically set to the RAID chunk size for arrays.
- opt_io_size to specify the optimal sustained I/O size, this is
typically the RAID stripe width for arrays.
I decided to not auto-probe these values from blkid which might easily
be possible as I don't know how to deal with these issues on migration.
Note that we specificly only set the physical_block_size, and not the
logial one which is the unit all I/O is described in. The reason for
that is that IDE does not support increasing the logical block size and
at last for now I want to stick to one meachnisms in queue and allow
for easy switching of transports for a given backing image which would
not be possible if scsi and virtio use real 4k sectors, while ide only
uses the physical block exponent.
To make this more common for the different block drivers introduce a
new BlockConf structure holding all common block properties and a
DEFINE_BLOCK_PROPERTIES macro to add them all together, mirroring
what is done for network drivers. Also switch over all block drivers
to use it, except for the floppy driver which has weird driveA/driveB
properties and probably won't require any advanced block options ever.
Example usage for a virtio device with 4k physical block size and
8k optimal I/O size:
-drive file=scratch.img,media=disk,cache=none,id=scratch \
-device virtio-blk-pci,drive=scratch,physical_block_size=4096,opt_io_size=8192
aliguori: updated patch to take into account BLOCK events
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-02-11 06:37:09 +08:00
|
|
|
#include "block_int.h"
|
2010-03-17 19:08:02 +08:00
|
|
|
#include "event_notifier.h"
|
2010-04-29 20:14:44 +08:00
|
|
|
#ifdef CONFIG_LINUX
|
|
|
|
#include "9p.h"
|
|
|
|
#endif
|
2008-12-05 03:38:57 +08:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
2009-12-09 02:07:48 +08:00
|
|
|
/* 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
|
|
|
|
|
2009-09-24 23:53:10 +08:00
|
|
|
/* We notify when the ring is completely used, even if the guest is suppressing
|
2008-12-05 03:38:57 +08:00
|
|
|
* callbacks */
|
|
|
|
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
2009-06-17 18:38:28 +08:00
|
|
|
/* We support indirect buffer descriptors */
|
|
|
|
#define VIRTIO_RING_F_INDIRECT_DESC 28
|
2011-06-12 21:21:57 +08:00
|
|
|
/* 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
|
2009-04-06 01:40:08 +08:00
|
|
|
/* A guest should never accept this. It implies negotiation is broken. */
|
|
|
|
#define VIRTIO_F_BAD_FEATURE 30
|
2008-12-05 03:38:57 +08:00
|
|
|
|
|
|
|
/* 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
|
2009-06-17 18:38:28 +08:00
|
|
|
/* This means the buffer contains a list of buffer descriptors. */
|
|
|
|
#define VRING_DESC_F_INDIRECT 4
|
2008-12-05 03:38:57 +08:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2009-10-02 05:12:16 +08:00
|
|
|
static inline target_phys_addr_t vring_align(target_phys_addr_t addr,
|
2008-12-05 03:58:45 +08:00
|
|
|
unsigned long align)
|
|
|
|
{
|
|
|
|
return (addr + align - 1) & ~(align - 1);
|
|
|
|
}
|
|
|
|
|
2008-12-05 03:38:57 +08:00
|
|
|
typedef struct VirtQueue VirtQueue;
|
|
|
|
|
|
|
|
#define VIRTQUEUE_MAX_SIZE 1024
|
|
|
|
|
|
|
|
typedef struct VirtQueueElement
|
|
|
|
{
|
|
|
|
unsigned int index;
|
|
|
|
unsigned int out_num;
|
|
|
|
unsigned int in_num;
|
2009-10-02 05:12:16 +08:00
|
|
|
target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE];
|
2010-08-03 22:54:38 +08:00
|
|
|
target_phys_addr_t out_addr[VIRTQUEUE_MAX_SIZE];
|
2008-12-05 03:38:57 +08:00
|
|
|
struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
|
|
|
|
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
|
|
|
|
} VirtQueueElement;
|
|
|
|
|
2009-05-18 21:51:59 +08:00
|
|
|
typedef struct {
|
2009-06-22 00:50:13 +08:00
|
|
|
void (*notify)(void * opaque, uint16_t vector);
|
2009-06-22 00:50:40 +08:00
|
|
|
void (*save_config)(void * opaque, QEMUFile *f);
|
|
|
|
void (*save_queue)(void * opaque, int n, QEMUFile *f);
|
|
|
|
int (*load_config)(void * opaque, QEMUFile *f);
|
|
|
|
int (*load_queue)(void * opaque, int n, QEMUFile *f);
|
2011-03-20 01:28:19 +08:00
|
|
|
int (*load_done)(void * opaque, QEMUFile *f);
|
2009-12-09 02:07:48 +08:00
|
|
|
unsigned (*get_features)(void * opaque);
|
2011-02-02 04:13:42 +08:00
|
|
|
bool (*query_guest_notifiers)(void * opaque);
|
2010-10-06 21:20:17 +08:00
|
|
|
int (*set_guest_notifiers)(void * opaque, bool assigned);
|
2010-03-17 19:08:02 +08:00
|
|
|
int (*set_host_notifier)(void * opaque, int n, bool assigned);
|
2011-01-10 20:28:40 +08:00
|
|
|
void (*vmstate_change)(void * opaque, bool running);
|
2009-05-18 21:51:59 +08:00
|
|
|
} VirtIOBindings;
|
|
|
|
|
2010-01-20 03:06:51 +08:00
|
|
|
#define VIRTIO_PCI_QUEUE_MAX 64
|
2008-12-05 03:38:57 +08:00
|
|
|
|
2009-06-22 00:50:13 +08:00
|
|
|
#define VIRTIO_NO_VECTOR 0xffff
|
|
|
|
|
2008-12-05 03:38:57 +08:00
|
|
|
struct VirtIODevice
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
uint8_t status;
|
|
|
|
uint8_t isr;
|
|
|
|
uint16_t queue_sel;
|
2010-01-10 19:52:47 +08:00
|
|
|
uint32_t guest_features;
|
2008-12-05 03:38:57 +08:00
|
|
|
size_t config_len;
|
|
|
|
void *config;
|
2009-06-22 00:50:13 +08:00
|
|
|
uint16_t config_vector;
|
|
|
|
int nvectors;
|
2010-01-10 19:52:53 +08:00
|
|
|
uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
|
2009-04-06 01:40:08 +08:00
|
|
|
uint32_t (*bad_features)(VirtIODevice *vdev);
|
2008-12-05 03:38:57 +08:00
|
|
|
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);
|
2010-03-17 19:08:05 +08:00
|
|
|
void (*set_status)(VirtIODevice *vdev, uint8_t val);
|
2008-12-05 03:38:57 +08:00
|
|
|
VirtQueue *vq;
|
2009-05-18 21:51:59 +08:00
|
|
|
const VirtIOBindings *binding;
|
|
|
|
void *binding_opaque;
|
|
|
|
uint16_t device_id;
|
2011-01-10 20:28:40 +08:00
|
|
|
bool vm_running;
|
|
|
|
VMChangeStateEntry *vmstate;
|
2008-12-05 03:38:57 +08:00
|
|
|
};
|
|
|
|
|
2010-03-17 19:08:05 +08:00
|
|
|
static inline void virtio_set_status(VirtIODevice *vdev, uint8_t val)
|
|
|
|
{
|
|
|
|
if (vdev->set_status) {
|
|
|
|
vdev->set_status(vdev, val);
|
|
|
|
}
|
|
|
|
vdev->status = val;
|
|
|
|
}
|
|
|
|
|
2008-12-05 03:38:57 +08:00
|
|
|
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);
|
|
|
|
|
2010-08-03 22:54:38 +08:00
|
|
|
void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr,
|
|
|
|
size_t num_sg, int is_write);
|
2008-12-05 03:38:57 +08:00
|
|
|
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);
|
|
|
|
|
2009-06-22 00:50:13 +08:00
|
|
|
int virtio_load(VirtIODevice *vdev, QEMUFile *f);
|
2008-12-05 03:38:57 +08:00
|
|
|
|
2009-04-18 01:11:08 +08:00
|
|
|
void virtio_cleanup(VirtIODevice *vdev);
|
|
|
|
|
2008-12-05 03:38:57 +08:00
|
|
|
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);
|
|
|
|
|
2009-05-18 21:51:59 +08:00
|
|
|
/* 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);
|
2009-10-02 05:12:16 +08:00
|
|
|
void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr);
|
|
|
|
target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n);
|
2009-05-18 21:51:59 +08:00
|
|
|
int virtio_queue_get_num(VirtIODevice *vdev, int n);
|
|
|
|
void virtio_queue_notify(VirtIODevice *vdev, int n);
|
2009-06-22 00:50:13 +08:00
|
|
|
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
|
|
|
|
void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
|
2009-05-18 21:51:59 +08:00
|
|
|
void virtio_reset(void *opaque);
|
|
|
|
void virtio_update_irq(VirtIODevice *vdev);
|
|
|
|
|
|
|
|
void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
|
|
|
void *opaque);
|
|
|
|
|
|
|
|
/* Base devices. */
|
2011-06-20 17:35:18 +08:00
|
|
|
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
|
|
|
|
char **serial);
|
2010-09-02 23:00:50 +08:00
|
|
|
struct virtio_net_conf;
|
|
|
|
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
|
|
|
struct virtio_net_conf *net);
|
2011-02-03 13:52:32 +08:00
|
|
|
typedef struct virtio_serial_conf virtio_serial_conf;
|
|
|
|
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
|
2009-05-18 21:51:59 +08:00
|
|
|
VirtIODevice *virtio_balloon_init(DeviceState *dev);
|
2010-04-29 20:14:44 +08:00
|
|
|
#ifdef CONFIG_LINUX
|
|
|
|
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
|
|
|
|
#endif
|
|
|
|
|
2009-05-18 21:51:59 +08:00
|
|
|
|
2009-10-21 21:25:35 +08:00
|
|
|
void virtio_net_exit(VirtIODevice *vdev);
|
2010-07-21 01:14:22 +08:00
|
|
|
void virtio_blk_exit(VirtIODevice *vdev);
|
2010-08-19 09:21:04 +08:00
|
|
|
void virtio_serial_exit(VirtIODevice *vdev);
|
2011-07-27 16:20:41 +08:00
|
|
|
void virtio_balloon_exit(VirtIODevice *vdev);
|
2009-10-21 21:25:35 +08:00
|
|
|
|
2010-01-10 19:52:53 +08:00
|
|
|
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
|
|
|
|
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
2011-06-12 21:21:57 +08:00
|
|
|
VIRTIO_RING_F_INDIRECT_DESC, true), \
|
|
|
|
DEFINE_PROP_BIT("event_idx", _state, _field, \
|
|
|
|
VIRTIO_RING_F_EVENT_IDX, true)
|
2010-01-10 19:52:53 +08:00
|
|
|
|
2010-03-17 19:08:02 +08:00
|
|
|
target_phys_addr_t virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t virtio_queue_get_used_addr(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t virtio_queue_get_ring_addr(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t virtio_queue_get_desc_size(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t virtio_queue_get_avail_size(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t virtio_queue_get_used_size(VirtIODevice *vdev, int n);
|
|
|
|
target_phys_addr_t 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);
|
|
|
|
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
|
|
|
|
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
|
2010-12-17 20:01:50 +08:00
|
|
|
void virtio_queue_notify_vq(VirtQueue *vq);
|
2010-03-17 19:08:02 +08:00
|
|
|
void virtio_irq(VirtQueue *vq);
|
2008-12-05 03:38:57 +08:00
|
|
|
#endif
|