Revision 5e9be92d

b/configure
179 179
xfs=""
180 180

  
181 181
vhost_net="no"
182
vhost_scsi="no"
182 183
kvm="no"
183 184
gprof="no"
184 185
debug_tcg="no"
......
543 544
  usb="linux"
544 545
  kvm="yes"
545 546
  vhost_net="yes"
547
  vhost_scsi="yes"
546 548
  if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
547 549
    audio_possible_drivers="$audio_possible_drivers fmod"
548 550
  fi
......
870 872
  ;;
871 873
  --enable-vhost-net) vhost_net="yes"
872 874
  ;;
875
  --disable-vhost-scsi) vhost_scsi="no"
876
  ;;
877
  --enable-vhost-scsi) vhost_scsi="yes"
878
  ;;
873 879
  --disable-glx) glx="no"
874 880
  ;;
875 881
  --enable-glx) glx="yes"
......
3553 3559
echo "uuid support      $uuid"
3554 3560
echo "libcap-ng support $cap_ng"
3555 3561
echo "vhost-net support $vhost_net"
3562
echo "vhost-scsi support $vhost_scsi"
3556 3563
echo "Trace backend     $trace_backend"
3557 3564
echo "Trace output file $trace_file-<pid>"
3558 3565
echo "spice support     $spice ($spice_protocol_version/$spice_server_version)"
......
3836 3843
if test "$virtfs" = "yes" ; then
3837 3844
  echo "CONFIG_VIRTFS=y" >> $config_host_mak
3838 3845
fi
3846
if test "$vhost_scsi" = "yes" ; then
3847
  echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak
3848
fi
3839 3849
if test "$blobs" = "yes" ; then
3840 3850
  echo "INSTALL_BLOBS=yes" >> $config_host_mak
3841 3851
fi
b/hw/scsi/Makefile.objs
6 6
common-obj-$(CONFIG_ESP) += esp.o
7 7
common-obj-$(CONFIG_ESP_PCI) += esp-pci.o
8 8
obj-$(CONFIG_PSERIES) += spapr_vscsi.o
9
obj-$(CONFIG_VIRTIO) += virtio-scsi.o
9

  
10
ifeq ($(CONFIG_VIRTIO),y)
11
obj-y += virtio-scsi.o
12
obj-$(CONFIG_VHOST_SCSI) += vhost-scsi.o
13
endif
b/hw/scsi/vhost-scsi.c
1
/*
2
 * vhost_scsi host device
3
 *
4
 * Copyright IBM, Corp. 2011
5
 *
6
 * Authors:
7
 *  Stefan Hajnoczi   <stefanha@linux.vnet.ibm.com>
8
 *
9
 * Changes for QEMU mainline + tcm_vhost kernel upstream:
10
 *  Nicholas Bellinger <nab@risingtidesystems.com>
11
 *
12
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
13
 * See the COPYING.LIB file in the top-level directory.
14
 *
15
 */
16

  
17
#include <sys/ioctl.h>
18
#include "config.h"
19
#include "qemu/queue.h"
20
#include "monitor/monitor.h"
21
#include "migration/migration.h"
22
#include "hw/virtio/vhost-scsi.h"
23
#include "hw/virtio/vhost.h"
24
#include "hw/virtio/virtio-scsi.h"
25

  
26
static int vhost_scsi_set_endpoint(VHostSCSI *s)
27
{
28
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
29
    struct vhost_scsi_target backend;
30
    int ret;
31

  
32
    memset(&backend, 0, sizeof(backend));
33
    pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
34
    ret = ioctl(s->dev.control, VHOST_SCSI_SET_ENDPOINT, &backend);
35
    if (ret < 0) {
36
        return -errno;
37
    }
38
    return 0;
39
}
40

  
41
static void vhost_scsi_clear_endpoint(VHostSCSI *s)
42
{
43
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
44
    struct vhost_scsi_target backend;
45

  
46
    memset(&backend, 0, sizeof(backend));
47
    pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
48
    ioctl(s->dev.control, VHOST_SCSI_CLEAR_ENDPOINT, &backend);
49
}
50

  
51
static int vhost_scsi_start(VHostSCSI *s)
52
{
53
    int ret, abi_version, i;
54
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
55

  
56
    if (!vdev->binding->set_guest_notifiers) {
57
        error_report("binding does not support guest notifiers");
58
        return -ENOSYS;
59
    }
60

  
61
    ret = ioctl(s->dev.control, VHOST_SCSI_GET_ABI_VERSION, &abi_version);
62
    if (ret < 0) {
63
        return -errno;
64
    }
65
    if (abi_version > VHOST_SCSI_ABI_VERSION) {
66
        error_report("vhost-scsi: The running tcm_vhost kernel abi_version:"
67
                     " %d is greater than vhost_scsi userspace supports: %d, please"
68
                     " upgrade your version of QEMU\n", abi_version,
69
                     VHOST_SCSI_ABI_VERSION);
70
        return -ENOSYS;
71
    }
72

  
73
    ret = vhost_dev_enable_notifiers(&s->dev, vdev);
74
    if (ret < 0) {
75
        return ret;
76
    }
77

  
78
    s->dev.acked_features = vdev->guest_features;
79
    ret = vhost_dev_start(&s->dev, vdev);
80
    if (ret < 0) {
81
        error_report("Error start vhost dev");
82
        goto err_notifiers;
83
    }
84

  
85
    ret = vhost_scsi_set_endpoint(s);
86
    if (ret < 0) {
87
        error_report("Error set vhost-scsi endpoint");
88
        goto err_vhost_stop;
89
    }
90

  
91
    ret = vdev->binding->set_guest_notifiers(vdev->binding_opaque, s->dev.nvqs, true);
92
    if (ret < 0) {
93
        error_report("Error binding guest notifier");
94
        goto err_endpoint;
95
    }
96

  
97
    /* guest_notifier_mask/pending not used yet, so just unmask
98
     * everything here.  virtio-pci will do the right thing by
99
     * enabling/disabling irqfd.
100
     */
101
    for (i = 0; i < s->dev.nvqs; i++) {
102
        vhost_virtqueue_mask(&s->dev, vdev, i, false);
103
    }
104

  
105
    return ret;
106

  
107
err_endpoint:
108
    vhost_scsi_clear_endpoint(s);
109
err_vhost_stop:
110
    vhost_dev_stop(&s->dev, vdev);
111
err_notifiers:
112
    vhost_dev_disable_notifiers(&s->dev, vdev);
113
    return ret;
114
}
115

  
116
static void vhost_scsi_stop(VHostSCSI *s)
117
{
118
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
119
    int ret = 0;
120

  
121
    if (!vdev->binding->set_guest_notifiers) {
122
        ret = vdev->binding->set_guest_notifiers(vdev->binding_opaque,
123
                                                 s->dev.nvqs, false);
124
        if (ret < 0) {
125
                error_report("vhost guest notifier cleanup failed: %d\n", ret);
126
        }
127
    }
128
    assert(ret >= 0);
129

  
130
    vhost_scsi_clear_endpoint(s);
131
    vhost_dev_stop(&s->dev, vdev);
132
    vhost_dev_disable_notifiers(&s->dev, vdev);
133
}
134

  
135
static uint32_t vhost_scsi_get_features(VirtIODevice *vdev,
136
                                        uint32_t features)
137
{
138
    VHostSCSI *s = VHOST_SCSI(vdev);
139

  
140
    /* Clear features not supported by host kernel. */
141
    if (!(s->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
142
        features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
143
    }
144
    if (!(s->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
145
        features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
146
    }
147
    if (!(s->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
148
        features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
149
    }
150
    if (!(s->dev.features & (1 << VIRTIO_SCSI_F_HOTPLUG))) {
151
        features &= ~(1 << VIRTIO_SCSI_F_HOTPLUG);
152
    }
153

  
154
    return features;
155
}
156

  
157
static void vhost_scsi_set_config(VirtIODevice *vdev,
158
                                  const uint8_t *config)
159
{
160
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
161
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
162

  
163
    if ((uint32_t) ldl_raw(&scsiconf->sense_size) != vs->sense_size ||
164
        (uint32_t) ldl_raw(&scsiconf->cdb_size) != vs->cdb_size) {
165
        error_report("vhost-scsi does not support changing the sense data and CDB sizes");
166
        exit(1);
167
    }
168
}
169

  
170
static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val)
171
{
172
    VHostSCSI *s = (VHostSCSI *)vdev;
173
    bool start = (val & VIRTIO_CONFIG_S_DRIVER_OK);
174

  
175
    if (s->dev.started == start) {
176
        return;
177
    }
178

  
179
    if (start) {
180
        int ret;
181

  
182
        ret = vhost_scsi_start(s);
183
        if (ret < 0) {
184
            error_report("virtio-scsi: unable to start vhost: %s\n",
185
                         strerror(-ret));
186

  
187
            /* There is no userspace virtio-scsi fallback so exit */
188
            exit(1);
189
        }
190
    } else {
191
        vhost_scsi_stop(s);
192
    }
193
}
194

  
195
static int vhost_scsi_init(VirtIODevice *vdev)
196
{
197
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
198
    VHostSCSI *s = VHOST_SCSI(vdev);
199
    int vhostfd = -1;
200
    int ret;
201

  
202
    if (!vs->conf.wwpn) {
203
        error_report("vhost-scsi: missing wwpn\n");
204
        return -EINVAL;
205
    }
206

  
207
    if (vs->conf.vhostfd) {
208
        vhostfd = monitor_handle_fd_param(cur_mon, vs->conf.vhostfd);
209
        if (vhostfd == -1) {
210
            error_report("vhost-scsi: unable to parse vhostfd\n");
211
            return -EINVAL;
212
        }
213
    }
214

  
215
    ret = virtio_scsi_common_init(vs);
216
    if (ret < 0) {
217
        return ret;
218
    }
219

  
220
    vdev->get_features = vhost_scsi_get_features;
221
    vdev->set_config = vhost_scsi_set_config;
222
    vdev->set_status = vhost_scsi_set_status;
223

  
224
    s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
225
    s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs);
226
    s->dev.vq_index = 0;
227

  
228
    ret = vhost_dev_init(&s->dev, vhostfd, "/dev/vhost-scsi", true);
229
    if (ret < 0) {
230
        error_report("vhost-scsi: vhost initialization failed: %s\n",
231
                strerror(-ret));
232
        return ret;
233
    }
234
    s->dev.backend_features = 0;
235

  
236
    error_setg(&s->migration_blocker,
237
            "vhost-scsi does not support migration");
238
    migrate_add_blocker(s->migration_blocker);
239

  
240
    return 0;
241
}
242

  
243
static int vhost_scsi_exit(DeviceState *qdev)
244
{
245
    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
246
    VHostSCSI *s = VHOST_SCSI(qdev);
247
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
248

  
249
    migrate_del_blocker(s->migration_blocker);
250
    error_free(s->migration_blocker);
251

  
252
    /* This will stop vhost backend. */
253
    vhost_scsi_set_status(vdev, 0);
254

  
255
    g_free(s->dev.vqs);
256
    return virtio_scsi_common_exit(vs);
257
}
258

  
259
static Property vhost_scsi_properties[] = {
260
    DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSI, parent_obj.conf),
261
    DEFINE_PROP_END_OF_LIST(),
262
};
263

  
264
static void vhost_scsi_class_init(ObjectClass *klass, void *data)
265
{
266
    DeviceClass *dc = DEVICE_CLASS(klass);
267
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
268
    dc->exit = vhost_scsi_exit;
269
    dc->props = vhost_scsi_properties;
270
    vdc->init = vhost_scsi_init;
271
    vdc->get_features = vhost_scsi_get_features;
272
    vdc->set_config = vhost_scsi_set_config;
273
    vdc->set_status = vhost_scsi_set_status;
274
}
275

  
276
static const TypeInfo vhost_scsi_info = {
277
    .name = TYPE_VHOST_SCSI,
278
    .parent = TYPE_VIRTIO_SCSI_COMMON,
279
    .instance_size = sizeof(VHostSCSI),
280
    .class_init = vhost_scsi_class_init,
281
};
282

  
283
static void virtio_register_types(void)
284
{
285
    type_register_static(&vhost_scsi_info);
286
}
287

  
288
type_init(virtio_register_types)
b/include/hw/virtio/vhost-scsi.h
1
/*
2
 * vhost_scsi host device
3
 *
4
 * Copyright IBM, Corp. 2011
5
 *
6
 * Authors:
7
 *  Stefan Hajnoczi   <stefanha@linux.vnet.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10
 * See the COPYING.LIB file in the top-level directory.
11
 *
12
 */
13

  
14
#ifndef VHOST_SCSI_H
15
#define VHOST_SCSI_H
16

  
17
#include "qemu-common.h"
18
#include "hw/qdev.h"
19
#include "hw/virtio/virtio-scsi.h"
20
#include "hw/virtio/vhost.h"
21

  
22
/*
23
 * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
24
 *
25
 * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
26
 *            RFC-v2 vhost-scsi userspace.  Add GET_ABI_VERSION ioctl usage
27
 * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
28
 * 	      All the targets under vhost_wwpn can be seen and used by guest.
29
 */
30

  
31
#define VHOST_SCSI_ABI_VERSION 1
32

  
33
/* TODO #include <linux/vhost.h> properly */
34
/* For VHOST_SCSI_SET_ENDPOINT/VHOST_SCSI_CLEAR_ENDPOINT ioctl */
35
struct vhost_scsi_target {
36
    int abi_version;
37
    char vhost_wwpn[224];
38
    unsigned short vhost_tpgt;
39
    unsigned short reserved;
40
};
41

  
42
enum vhost_scsi_vq_list {
43
    VHOST_SCSI_VQ_CONTROL = 0,
44
    VHOST_SCSI_VQ_EVENT = 1,
45
    VHOST_SCSI_VQ_NUM_FIXED = 2,
46
};
47

  
48
#define VHOST_VIRTIO 0xAF
49
#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
50
#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
51
#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
52

  
53
#define TYPE_VHOST_SCSI "vhost-scsi"
54
#define VHOST_SCSI(obj) \
55
        OBJECT_CHECK(VHostSCSI, (obj), TYPE_VHOST_SCSI)
56

  
57
typedef struct VHostSCSI {
58
    VirtIOSCSICommon parent_obj;
59

  
60
    Error *migration_blocker;
61

  
62
    struct vhost_dev dev;
63
} VHostSCSI;
64

  
65
#define DEFINE_VHOST_SCSI_PROPERTIES(_state, _conf_field) \
66
    DEFINE_PROP_STRING("vhostfd", _state, _conf_field.vhostfd), \
67
    DEFINE_PROP_STRING("wwpn", _state, _conf_field.wwpn), \
68
    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
69
    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
70
    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
71

  
72

  
73
#endif
b/include/hw/virtio/virtio-scsi.h
151 151
    uint32_t num_queues;
152 152
    uint32_t max_sectors;
153 153
    uint32_t cmd_per_lun;
154
    char *vhostfd;
155
    char *wwpn;
154 156
};
155 157

  
156 158
typedef struct VirtIOSCSICommon {

Also available in: Unified diff