virtio-scsi: Add virtio-scsi stub device

Add a useless virtio SCSI HBA device:

  qemu -device virtio-scsi-pci

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2011-02-11 08:40:59 +00:00 committed by Paolo Bonzini
parent 43b978b932
commit 973abc7f41
11 changed files with 364 additions and 0 deletions

View File

@ -200,6 +200,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
# need to fix this properly
obj-$(CONFIG_NO_PCI) += pci-stub.o
obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o

View File

@ -1,5 +1,6 @@
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_SCSI=y
CONFIG_VIRTIO=y
CONFIG_USB_UHCI=y
CONFIG_USB_OHCI=y

View File

@ -1 +1,2 @@
CONFIG_VIRTIO=y
CONFIG_VIRTIO_SCSI=y

View File

@ -75,6 +75,7 @@
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004
#define FMT_PCIBUS PRIx64

View File

@ -169,6 +169,18 @@ static int s390_virtio_serial_init(VirtIOS390Device *dev)
return r;
}
static int s390_virtio_scsi_init(VirtIOS390Device *dev)
{
VirtIODevice *vdev;
vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
if (!vdev) {
return -1;
}
return s390_virtio_device_init(dev, vdev);
}
static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
{
ram_addr_t token_off;
@ -433,6 +445,26 @@ static TypeInfo virtio_s390_device_info = {
.abstract = true,
};
static Property s390_virtio_scsi_properties[] = {
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi),
DEFINE_PROP_END_OF_LIST(),
};
static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
k->init = s390_virtio_scsi_init;
dc->props = s390_virtio_scsi_properties;
}
static TypeInfo s390_virtio_scsi = {
.name = "virtio-scsi-s390",
.parent = TYPE_VIRTIO_S390_DEVICE,
.instance_size = sizeof(VirtIOS390Device),
.class_init = s390_virtio_scsi_class_init,
};
/***************** S390 Virtio Bus Bridge Device *******************/
/* Only required to have the virtio bus as child in the system bus */
@ -465,6 +497,7 @@ static void s390_virtio_register_types(void)
type_register_static(&s390_virtio_serial);
type_register_static(&s390_virtio_blk);
type_register_static(&s390_virtio_net);
type_register_static(&s390_virtio_scsi);
type_register_static(&s390_virtio_bridge_info);
}

View File

@ -19,6 +19,7 @@
#include "virtio-net.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */
#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */
@ -67,6 +68,7 @@ struct VirtIOS390Device {
uint32_t host_features;
virtio_serial_conf serial;
virtio_net_conf net;
VirtIOSCSIConf scsi;
};
typedef struct VirtIOS390Bus {

View File

@ -21,6 +21,7 @@
#include "virtio-blk.h"
#include "virtio-net.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
#include "pci.h"
#include "qemu-error.h"
#include "msix.h"
@ -930,12 +931,67 @@ static TypeInfo virtio_balloon_info = {
.class_init = virtio_balloon_class_init,
};
static int virtio_scsi_init_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
VirtIODevice *vdev;
vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
if (!vdev) {
return -EINVAL;
}
vdev->nvectors = proxy->nvectors;
virtio_init_pci(proxy, vdev);
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
return 0;
}
static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
virtio_scsi_exit(proxy->vdev);
return virtio_exit_pci(pci_dev);
}
static Property virtio_scsi_properties[] = {
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
DEFINE_PROP_END_OF_LIST(),
};
static void virtio_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->init = virtio_scsi_init_pci;
k->exit = virtio_scsi_exit_pci;
k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
k->revision = 0x00;
k->class_id = PCI_CLASS_STORAGE_SCSI;
dc->reset = virtio_pci_reset;
dc->props = virtio_scsi_properties;
}
static TypeInfo virtio_scsi_info = {
.name = "virtio-scsi-pci",
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(VirtIOPCIProxy),
.class_init = virtio_scsi_class_init,
};
static void virtio_pci_register_types(void)
{
type_register_static(&virtio_blk_info);
type_register_static(&virtio_net_info);
type_register_static(&virtio_serial_info);
type_register_static(&virtio_balloon_info);
type_register_static(&virtio_scsi_info);
}
type_init(virtio_pci_register_types)

View File

@ -17,6 +17,7 @@
#include "virtio-net.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
/* Performance improves when virtqueue kick processing is decoupled from the
* vcpu thread using ioeventfd for some devices. */
@ -40,6 +41,7 @@ typedef struct {
#endif
virtio_serial_conf serial;
virtio_net_conf net;
VirtIOSCSIConf scsi;
bool ioeventfd_disabled;
bool ioeventfd_started;
} VirtIOPCIProxy;

228
hw/virtio-scsi.c Normal file
View File

@ -0,0 +1,228 @@
/*
* Virtio SCSI HBA
*
* Copyright IBM, Corp. 2010
* Copyright Red Hat, Inc. 2011
*
* Authors:
* Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
* Paolo Bonzini <pbonzini@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.
*
*/
#include "virtio-scsi.h"
#include <hw/scsi.h>
#include <hw/scsi-defs.h>
#define VIRTIO_SCSI_VQ_SIZE 128
#define VIRTIO_SCSI_CDB_SIZE 32
#define VIRTIO_SCSI_SENSE_SIZE 96
#define VIRTIO_SCSI_MAX_CHANNEL 0
#define VIRTIO_SCSI_MAX_TARGET 255
#define VIRTIO_SCSI_MAX_LUN 16383
/* Response codes */
#define VIRTIO_SCSI_S_OK 0
#define VIRTIO_SCSI_S_OVERRUN 1
#define VIRTIO_SCSI_S_ABORTED 2
#define VIRTIO_SCSI_S_BAD_TARGET 3
#define VIRTIO_SCSI_S_RESET 4
#define VIRTIO_SCSI_S_BUSY 5
#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
#define VIRTIO_SCSI_S_TARGET_FAILURE 7
#define VIRTIO_SCSI_S_NEXUS_FAILURE 8
#define VIRTIO_SCSI_S_FAILURE 9
#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
#define VIRTIO_SCSI_S_INCORRECT_LUN 12
/* Controlq type codes. */
#define VIRTIO_SCSI_T_TMF 0
#define VIRTIO_SCSI_T_AN_QUERY 1
#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
/* Valid TMF subtypes. */
#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
/* Events. */
#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
#define VIRTIO_SCSI_T_NO_EVENT 0
#define VIRTIO_SCSI_T_TRANSPORT_RESET 1
#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
/* SCSI command request, followed by data-out */
typedef struct {
uint8_t lun[8]; /* Logical Unit Number */
uint64_t tag; /* Command identifier */
uint8_t task_attr; /* Task attribute */
uint8_t prio;
uint8_t crn;
uint8_t cdb[];
} QEMU_PACKED VirtIOSCSICmdReq;
/* Response, followed by sense data and data-in */
typedef struct {
uint32_t sense_len; /* Sense data length */
uint32_t resid; /* Residual bytes in data buffer */
uint16_t status_qualifier; /* Status qualifier */
uint8_t status; /* Command completion status */
uint8_t response; /* Response values */
uint8_t sense[];
} QEMU_PACKED VirtIOSCSICmdResp;
/* Task Management Request */
typedef struct {
uint32_t type;
uint32_t subtype;
uint8_t lun[8];
uint64_t tag;
} QEMU_PACKED VirtIOSCSICtrlTMFReq;
typedef struct {
uint8_t response;
} QEMU_PACKED VirtIOSCSICtrlTMFResp;
/* Asynchronous notification query/subscription */
typedef struct {
uint32_t type;
uint8_t lun[8];
uint32_t event_requested;
} QEMU_PACKED VirtIOSCSICtrlANReq;
typedef struct {
uint32_t event_actual;
uint8_t response;
} QEMU_PACKED VirtIOSCSICtrlANResp;
typedef struct {
uint32_t event;
uint8_t lun[8];
uint32_t reason;
} QEMU_PACKED VirtIOSCSIEvent;
typedef struct {
uint32_t num_queues;
uint32_t seg_max;
uint32_t max_sectors;
uint32_t cmd_per_lun;
uint32_t event_info_size;
uint32_t sense_size;
uint32_t cdb_size;
uint16_t max_channel;
uint16_t max_target;
uint32_t max_lun;
} QEMU_PACKED VirtIOSCSIConfig;
typedef struct {
VirtIODevice vdev;
DeviceState *qdev;
VirtIOSCSIConf *conf;
VirtQueue *ctrl_vq;
VirtQueue *event_vq;
VirtQueue *cmd_vq;
uint32_t sense_size;
uint32_t cdb_size;
} VirtIOSCSI;
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
/* TODO */
}
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
{
/* TODO */
}
static void virtio_scsi_get_config(VirtIODevice *vdev,
uint8_t *config)
{
VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
stl_raw(&scsiconf->num_queues, s->conf->num_queues);
stl_raw(&scsiconf->seg_max, 128 - 2);
stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
stl_raw(&scsiconf->sense_size, s->sense_size);
stl_raw(&scsiconf->cdb_size, s->cdb_size);
stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
}
static void virtio_scsi_set_config(VirtIODevice *vdev,
const uint8_t *config)
{
VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
(uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
error_report("bad data written to virtio-scsi configuration space");
exit(1);
}
s->sense_size = ldl_raw(&scsiconf->sense_size);
s->cdb_size = ldl_raw(&scsiconf->cdb_size);
}
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
uint32_t requested_features)
{
return requested_features;
}
static void virtio_scsi_reset(VirtIODevice *vdev)
{
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
}
VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
{
VirtIOSCSI *s;
s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
sizeof(VirtIOSCSIConfig),
sizeof(VirtIOSCSI));
s->qdev = dev;
s->conf = proxyconf;
/* TODO set up vdev function pointers */
s->vdev.get_config = virtio_scsi_get_config;
s->vdev.set_config = virtio_scsi_set_config;
s->vdev.get_features = virtio_scsi_get_features;
s->vdev.reset = virtio_scsi_reset;
s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
virtio_scsi_handle_ctrl);
s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
NULL);
s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
virtio_scsi_handle_cmd);
/* TODO savevm */
return &s->vdev;
}
void virtio_scsi_exit(VirtIODevice *vdev)
{
virtio_cleanup(vdev);
}

36
hw/virtio-scsi.h Normal file
View File

@ -0,0 +1,36 @@
/*
* 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 "virtio.h"
#include "net.h"
#include "pci.h"
/* The ID for virtio_scsi */
#define VIRTIO_ID_SCSI 8
struct VirtIOSCSIConf {
uint32_t num_queues;
uint32_t max_sectors;
uint32_t cmd_per_lun;
};
#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_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)
#endif /* _QEMU_VIRTIO_SCSI_H */

View File

@ -199,6 +199,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
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);
#ifdef CONFIG_LINUX
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
#endif
@ -208,6 +210,7 @@ void virtio_net_exit(VirtIODevice *vdev);
void virtio_blk_exit(VirtIODevice *vdev);
void virtio_serial_exit(VirtIODevice *vdev);
void virtio_balloon_exit(VirtIODevice *vdev);
void virtio_scsi_exit(VirtIODevice *vdev);
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
DEFINE_PROP_BIT("indirect_desc", _state, _field, \