virtio-scsi.c 31.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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.
 *
 */

P
Peter Maydell 已提交
16
#include "qemu/osdep.h"
17
#include "qapi/error.h"
18
#include "standard-headers/linux/virtio_ids.h"
P
Paolo Bonzini 已提交
19
#include "hw/virtio/virtio-scsi.h"
20
#include "qemu/error-report.h"
21
#include "qemu/iov.h"
22
#include "sysemu/block-backend.h"
P
Paolo Bonzini 已提交
23 24 25
#include <hw/scsi/scsi.h>
#include <block/scsi.h>
#include <hw/virtio/virtio-bus.h>
26
#include "hw/virtio/virtio-access.h"
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
static inline int virtio_scsi_get_lun(uint8_t *lun)
{
    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
}

static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
{
    if (lun[0] != 1) {
        return NULL;
    }
    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
        return NULL;
    }
    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
}

44
void virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq, VirtIOSCSIReq *req)
45
{
46 47
    const size_t zero_skip =
        offsetof(VirtIOSCSIReq, resp_iov) + sizeof(req->resp_iov);
48 49 50 51

    req->vq = vq;
    req->dev = s;
    qemu_sglist_init(&req->qsgl, DEVICE(s), 8, &address_space_memory);
52
    qemu_iovec_init(&req->resp_iov, 1);
53
    memset((uint8_t *)req + zero_skip, 0, sizeof(*req) - zero_skip);
54 55
}

56
void virtio_scsi_free_req(VirtIOSCSIReq *req)
57
{
58
    qemu_iovec_destroy(&req->resp_iov);
59
    qemu_sglist_destroy(&req->qsgl);
60
    g_free(req);
61 62
}

63 64 65 66
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
{
    VirtIOSCSI *s = req->dev;
    VirtQueue *vq = req->vq;
67
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
68 69

    qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size);
70
    virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
P
Paolo Bonzini 已提交
71
    if (s->dataplane_started && !s->dataplane_fenced) {
72
        virtio_scsi_dataplane_notify(vdev, req);
F
Fam Zheng 已提交
73 74 75 76
    } else {
        virtio_notify(vdev, vq);
    }

77 78 79 80
    if (req->sreq) {
        req->sreq->hba_private = NULL;
        scsi_req_unref(req->sreq);
    }
81
    virtio_scsi_free_req(req);
82 83 84 85 86 87 88 89
}

static void virtio_scsi_bad_req(void)
{
    error_report("wrong size for virtio-scsi headers");
    exit(1);
}

90 91
static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
                              hwaddr *addr, int num, size_t skip)
92
{
93
    QEMUSGList *qsgl = &req->qsgl;
94 95 96 97 98 99 100 101 102 103 104 105 106
    size_t copied = 0;

    while (num) {
        if (skip >= iov->iov_len) {
            skip -= iov->iov_len;
        } else {
            qemu_sglist_add(qsgl, *addr + skip, iov->iov_len - skip);
            copied += iov->iov_len - skip;
            skip = 0;
        }
        iov++;
        addr++;
        num--;
107
    }
108 109 110

    assert(skip == 0);
    return copied;
111 112
}

113 114
static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
                                 unsigned req_size, unsigned resp_size)
115
{
116
    VirtIODevice *vdev = (VirtIODevice *) req->dev;
117
    size_t in_size, out_size;
118

119 120
    if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
                   &req->req, req_size) < req_size) {
121 122 123
        return -EINVAL;
    }

124 125 126
    if (qemu_iovec_concat_iov(&req->resp_iov,
                              req->elem.in_sg, req->elem.in_num, 0,
                              resp_size) < resp_size) {
127 128
        return -EINVAL;
    }
129

130
    req->resp_size = resp_size;
131

132 133 134 135 136 137 138 139 140 141
    /* Old BIOSes left some padding by mistake after the req_size/resp_size.
     * As a workaround, always consider the first buffer as the virtio-scsi
     * request/response, making the payload start at the second element
     * of the iovec.
     *
     * The actual length of the response header, stored in req->resp_size,
     * does not change.
     *
     * TODO: always disable this workaround for virtio 1.0 devices.
     */
142
    if (!virtio_vdev_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
143 144 145 146 147 148
        if (req->elem.out_num) {
            req_size = req->elem.out_sg[0].iov_len;
        }
        if (req->elem.in_num) {
            resp_size = req->elem.in_sg[0].iov_len;
        }
149 150
    }

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    out_size = qemu_sgl_concat(req, req->elem.out_sg,
                               &req->elem.out_addr[0], req->elem.out_num,
                               req_size);
    in_size = qemu_sgl_concat(req, req->elem.in_sg,
                              &req->elem.in_addr[0], req->elem.in_num,
                              resp_size);

    if (out_size && in_size) {
        return -ENOTSUP;
    }

    if (out_size) {
        req->mode = SCSI_XFER_TO_DEV;
    } else if (in_size) {
        req->mode = SCSI_XFER_FROM_DEV;
166
    }
167 168

    return 0;
169 170 171 172
}

static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
{
173 174 175 176 177
    VirtIOSCSICommon *vs = (VirtIOSCSICommon *)s;
    VirtIOSCSIReq *req;

    req = virtqueue_pop(vq, sizeof(VirtIOSCSIReq) + vs->cdb_size);
    if (!req) {
178 179
        return NULL;
    }
180
    virtio_scsi_init_req(s, vq, req);
181 182 183
    return req;
}

184 185 186
static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
{
    VirtIOSCSIReq *req = sreq->hba_private;
187
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
188
    uint32_t n = virtio_queue_get_id(req->vq) - 2;
189

190
    assert(n < vs->conf.num_queues);
191
    qemu_put_be32s(f, &n);
192
    qemu_put_virtqueue_element(f, &req->elem);
193 194 195 196 197 198
}

static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
{
    SCSIBus *bus = sreq->bus;
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
199
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
200
    VirtIOSCSIReq *req;
201
    uint32_t n;
202

203
    qemu_get_be32s(f, &n);
204
    assert(n < vs->conf.num_queues);
205
    req = qemu_get_virtqueue_element(f, sizeof(VirtIOSCSIReq) + vs->cdb_size);
206
    virtio_scsi_init_req(s, vs->cmd_vqs[n], req);
207

208 209 210 211 212
    if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
                              sizeof(VirtIOSCSICmdResp) + vs->sense_size) < 0) {
        error_report("invalid SCSI request migration data");
        exit(1);
    }
213 214 215 216

    scsi_req_ref(sreq);
    req->sreq = sreq;
    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
217
        assert(req->sreq->cmd.mode == req->mode);
218 219 220 221
    }
    return req;
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235
typedef struct {
    Notifier        notifier;
    VirtIOSCSIReq  *tmf_req;
} VirtIOSCSICancelNotifier;

static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
{
    VirtIOSCSICancelNotifier *n = container_of(notifier,
                                               VirtIOSCSICancelNotifier,
                                               notifier);

    if (--n->tmf_req->remaining == 0) {
        virtio_scsi_complete_req(n->tmf_req);
    }
236
    g_free(n);
237 238 239 240 241 242
}

/* Return 0 if the request is ready to be completed and return to guest;
 * -EINPROGRESS if the request is submitted and will be completed later, in the
 *  case of async cancellation. */
static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
243
{
244
    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf.lun);
245
    SCSIRequest *r, *next;
A
Anthony Liguori 已提交
246
    BusChild *kid;
247
    int target;
248
    int ret = 0;
249

250
    if (s->dataplane_started && d) {
251
        assert(blk_get_aio_context(d->conf.blk) == s->ctx);
F
Fam Zheng 已提交
252
    }
253
    /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
254
    req->resp.tmf.response = VIRTIO_SCSI_S_OK;
255

256
    virtio_tswap32s(VIRTIO_DEVICE(s), &req->req.tmf.subtype);
257
    switch (req->req.tmf.subtype) {
258 259 260 261 262
    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
        if (!d) {
            goto fail;
        }
263
        if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
264 265 266
            goto incorrect_lun;
        }
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
267
            VirtIOSCSIReq *cmd_req = r->hba_private;
268
            if (cmd_req && cmd_req->req.cmd.tag == req->req.tmf.tag) {
269 270 271
                break;
            }
        }
272 273 274 275 276 277
        if (r) {
            /*
             * Assert that the request has not been completed yet, we
             * check for it in the loop above.
             */
            assert(r->hba_private);
278
            if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
279 280 281
                /* "If the specified command is present in the task set, then
                 * return a service response set to FUNCTION SUCCEEDED".
                 */
282
                req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
283
            } else {
284 285 286
                VirtIOSCSICancelNotifier *notifier;

                req->remaining = 1;
287
                notifier = g_new(VirtIOSCSICancelNotifier, 1);
288 289 290 291
                notifier->tmf_req = req;
                notifier->notifier.notify = virtio_scsi_cancel_notify;
                scsi_req_cancel_async(r, &notifier->notifier);
                ret = -EINPROGRESS;
292 293 294 295 296 297 298 299
            }
        }
        break;

    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
        if (!d) {
            goto fail;
        }
300
        if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
301 302 303 304 305 306 307 308 309 310 311 312 313
            goto incorrect_lun;
        }
        s->resetting++;
        qdev_reset_all(&d->qdev);
        s->resetting--;
        break;

    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
        if (!d) {
            goto fail;
        }
314
        if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
315 316
            goto incorrect_lun;
        }
317 318 319 320 321 322 323

        /* Add 1 to "remaining" until virtio_scsi_do_tmf returns.
         * This way, if the bus starts calling back to the notifiers
         * even before we finish the loop, virtio_scsi_cancel_notify
         * will not complete the TMF too early.
         */
        req->remaining = 1;
324 325
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
            if (r->hba_private) {
326
                if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
327 328 329
                    /* "If there is any command present in the task set, then
                     * return a service response set to FUNCTION SUCCEEDED".
                     */
330
                    req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
331 332
                    break;
                } else {
333 334 335
                    VirtIOSCSICancelNotifier *notifier;

                    req->remaining++;
336
                    notifier = g_new(VirtIOSCSICancelNotifier, 1);
337 338 339
                    notifier->notifier.notify = virtio_scsi_cancel_notify;
                    notifier->tmf_req = req;
                    scsi_req_cancel_async(r, &notifier->notifier);
340 341 342
                }
            }
        }
343 344 345
        if (--req->remaining > 0) {
            ret = -EINPROGRESS;
        }
346 347 348
        break;

    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
349
        target = req->req.tmf.lun[1];
350
        s->resetting++;
A
Anthony Liguori 已提交
351
        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
C
Cao jin 已提交
352
             d = SCSI_DEVICE(kid->child);
353 354 355 356 357 358 359 360 361
             if (d->channel == 0 && d->id == target) {
                qdev_reset_all(&d->qdev);
             }
        }
        s->resetting--;
        break;

    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
    default:
362
        req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
363
        break;
364 365
    }

366
    return ret;
367 368

incorrect_lun:
369
    req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
370
    return ret;
371 372

fail:
373
    req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
374
    return ret;
375 376
}

377
static void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
378
{
379
    VirtIODevice *vdev = (VirtIODevice *)s;
380
    uint32_t type;
381
    int r = 0;
382

383 384 385 386 387
    if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
                &type, sizeof(type)) < sizeof(type)) {
        virtio_scsi_bad_req();
        return;
    }
388

389 390
    virtio_tswap32s(vdev, &type);
    if (type == VIRTIO_SCSI_T_TMF) {
391 392
        if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
                    sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
393
            virtio_scsi_bad_req();
394
        } else {
395
            r = virtio_scsi_do_tmf(s, req);
396
        }
397

398 399
    } else if (type == VIRTIO_SCSI_T_AN_QUERY ||
               type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
400 401 402 403 404 405
        if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
                    sizeof(VirtIOSCSICtrlANResp)) < 0) {
            virtio_scsi_bad_req();
        } else {
            req->resp.an.event_actual = 0;
            req->resp.an.response = VIRTIO_SCSI_S_OK;
406
        }
407
    }
408 409 410 411 412
    if (r == 0) {
        virtio_scsi_complete_req(req);
    } else {
        assert(r == -EINPROGRESS);
    }
413 414
}

415
void virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq)
416 417 418 419 420
{
    VirtIOSCSIReq *req;

    while ((req = virtio_scsi_pop_req(s, vq))) {
        virtio_scsi_handle_ctrl_req(s, req);
421 422 423
    }
}

424 425 426 427 428 429 430 431 432 433 434 435 436
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;

    if (s->ctx) {
        virtio_scsi_dataplane_start(s);
        if (!s->dataplane_fenced) {
            return;
        }
    }
    virtio_scsi_handle_ctrl_vq(s, vq);
}

437 438
static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
{
439 440 441 442
    /* Sense data is not in req->resp and is copied separately
     * in virtio_scsi_command_complete.
     */
    req->resp_size = sizeof(VirtIOSCSICmdResp);
443 444 445
    virtio_scsi_complete_req(req);
}

446 447 448 449
static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
                                         size_t resid)
{
    VirtIOSCSIReq *req = r->hba_private;
450
    uint8_t sense[SCSI_SENSE_BUF_SIZE];
451
    uint32_t sense_len;
452
    VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
453

454 455 456 457
    if (r->io_canceled) {
        return;
    }

458 459 460
    req->resp.cmd.response = VIRTIO_SCSI_S_OK;
    req->resp.cmd.status = status;
    if (req->resp.cmd.status == GOOD) {
461
        req->resp.cmd.resid = virtio_tswap32(vdev, resid);
462
    } else {
463
        req->resp.cmd.resid = 0;
464
        sense_len = scsi_req_get_sense(r, sense, sizeof(sense));
465 466
        sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
        qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd),
467
                            sense, sense_len);
468
        req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len);
469
    }
470
    virtio_scsi_complete_cmd_req(req);
471 472
}

P
Paolo Bonzini 已提交
473 474 475 476 477 478
static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
                                 uint8_t *buf, void *hba_private)
{
    VirtIOSCSIReq *req = hba_private;

    if (cmd->len == 0) {
479
        cmd->len = MIN(VIRTIO_SCSI_CDB_DEFAULT_SIZE, SCSI_CMD_BUF_SIZE);
P
Paolo Bonzini 已提交
480 481 482 483 484 485 486
        memcpy(cmd->buf, buf, cmd->len);
    }

    /* Extract the direction and mode directly from the request, for
     * host device passthrough.
     */
    cmd->xfer = req->qsgl.size;
487
    cmd->mode = req->mode;
P
Paolo Bonzini 已提交
488 489 490
    return 0;
}

491 492 493 494 495 496 497 498 499 500 501 502 503 504
static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
{
    VirtIOSCSIReq *req = r->hba_private;

    return &req->qsgl;
}

static void virtio_scsi_request_cancelled(SCSIRequest *r)
{
    VirtIOSCSIReq *req = r->hba_private;

    if (!req) {
        return;
    }
505
    if (req->dev->resetting) {
506
        req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
507
    } else {
508
        req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
509
    }
510
    virtio_scsi_complete_cmd_req(req);
511 512 513
}

static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
514
{
515
    req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
516
    virtio_scsi_complete_cmd_req(req);
517 518
}

519
static bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
520 521 522 523 524 525 526 527 528 529 530 531 532
{
    VirtIOSCSICommon *vs = &s->parent_obj;
    SCSIDevice *d;
    int rc;

    rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
                               sizeof(VirtIOSCSICmdResp) + vs->sense_size);
    if (rc < 0) {
        if (rc == -ENOTSUP) {
            virtio_scsi_fail_cmd_req(req);
        } else {
            virtio_scsi_bad_req();
        }
533
        return false;
534 535 536 537 538 539
    }

    d = virtio_scsi_device_find(s, req->req.cmd.lun);
    if (!d) {
        req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
        virtio_scsi_complete_cmd_req(req);
540
        return false;
541
    }
542 543
    if (s->dataplane_started) {
        assert(blk_get_aio_context(d->conf.blk) == s->ctx);
F
Fam Zheng 已提交
544
    }
545 546
    req->sreq = scsi_req_new(d, req->req.cmd.tag,
                             virtio_scsi_get_lun(req->req.cmd.lun),
547
                             req->req.cmd.cdb, req);
548 549 550 551 552 553

    if (req->sreq->cmd.mode != SCSI_XFER_NONE
        && (req->sreq->cmd.mode != req->mode ||
            req->sreq->cmd.xfer > req->qsgl.size)) {
        req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
        virtio_scsi_complete_cmd_req(req);
554
        return false;
555
    }
556
    scsi_req_ref(req->sreq);
557
    blk_io_plug(d->conf.blk);
558 559
    return true;
}
560

561
static void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req)
562
{
563 564 565
    SCSIRequest *sreq = req->sreq;
    if (scsi_req_enqueue(sreq)) {
        scsi_req_continue(sreq);
566
    }
567
    blk_io_unplug(sreq->dev->conf.blk);
568
    scsi_req_unref(sreq);
569 570
}

571
void virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
572
{
573 574
    VirtIOSCSIReq *req, *next;
    QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
575 576

    while ((req = virtio_scsi_pop_req(s, vq))) {
577
        if (virtio_scsi_handle_cmd_req_prepare(s, req)) {
578
            QTAILQ_INSERT_TAIL(&reqs, req, next);
579
        }
580
    }
581 582 583 584

    QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
        virtio_scsi_handle_cmd_req_submit(s, req);
    }
585 586
}

587 588 589 590 591 592 593 594 595 596 597 598 599 600
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
{
    /* use non-QOM casts in the data path */
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;

    if (s->ctx) {
        virtio_scsi_dataplane_start(s);
        if (!s->dataplane_fenced) {
            return;
        }
    }
    virtio_scsi_handle_cmd_vq(s, vq);
}

601 602 603 604
static void virtio_scsi_get_config(VirtIODevice *vdev,
                                   uint8_t *config)
{
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
605
    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
606

607 608 609 610 611 612 613 614 615 616
    virtio_stl_p(vdev, &scsiconf->num_queues, s->conf.num_queues);
    virtio_stl_p(vdev, &scsiconf->seg_max, 128 - 2);
    virtio_stl_p(vdev, &scsiconf->max_sectors, s->conf.max_sectors);
    virtio_stl_p(vdev, &scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
    virtio_stl_p(vdev, &scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
    virtio_stl_p(vdev, &scsiconf->sense_size, s->sense_size);
    virtio_stl_p(vdev, &scsiconf->cdb_size, s->cdb_size);
    virtio_stw_p(vdev, &scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
    virtio_stw_p(vdev, &scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
    virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
617 618 619 620 621 622
}

static void virtio_scsi_set_config(VirtIODevice *vdev,
                                   const uint8_t *config)
{
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
623
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
624

625 626
    if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) >= 65536 ||
        (uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) >= 256) {
627 628 629 630
        error_report("bad data written to virtio-scsi configuration space");
        exit(1);
    }

631 632
    vs->sense_size = virtio_ldl_p(vdev, &scsiconf->sense_size);
    vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size);
633 634
}

G
Gerd Hoffmann 已提交
635
static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
J
Jason Wang 已提交
636 637
                                         uint64_t requested_features,
                                         Error **errp)
638
{
639 640 641 642
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);

    /* Firstly sync all virtio-scsi possible supported features */
    requested_features |= s->host_features;
643 644 645 646 647
    return requested_features;
}

static void virtio_scsi_reset(VirtIODevice *vdev)
{
648 649
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
650

F
Fam Zheng 已提交
651 652 653
    if (s->ctx) {
        virtio_scsi_dataplane_stop(s);
    }
654 655 656 657
    s->resetting++;
    qbus_reset_all(&s->bus.qbus);
    s->resetting--;

658 659
    vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
    vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
660
    s->events_dropped = false;
661 662
}

663 664 665 666 667
/* The device does not have anything to save beyond the virtio data.
 * Request data is saved with callbacks from SCSI devices.
 */
static void virtio_scsi_save(QEMUFile *f, void *opaque)
{
668
    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
669 670 671 672 673
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);

    if (s->dataplane_started) {
        virtio_scsi_dataplane_stop(s);
    }
674
    virtio_save(vdev, f);
675 676 677 678
}

static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
{
679
    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
680 681
    int ret;

682
    ret = virtio_load(vdev, f, version_id);
683 684 685
    if (ret) {
        return ret;
    }
686 687 688
    return 0;
}

689 690
void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
                            uint32_t event, uint32_t reason)
691
{
692
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
693
    VirtIOSCSIReq *req;
694
    VirtIOSCSIEvent *evt;
695
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
696

697
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
698 699 700
        return;
    }

F
Fam Zheng 已提交
701 702 703 704 705
    if (s->dataplane_started) {
        assert(s->ctx);
        aio_context_acquire(s->ctx);
    }

706
    req = virtio_scsi_pop_req(s, vs->event_vq);
707 708
    if (!req) {
        s->events_dropped = true;
F
Fam Zheng 已提交
709
        goto out;
710
    }
711

712 713 714 715 716
    if (s->events_dropped) {
        event |= VIRTIO_SCSI_T_EVENTS_MISSED;
        s->events_dropped = false;
    }

717
    if (virtio_scsi_parse_req(req, 0, sizeof(VirtIOSCSIEvent))) {
718 719 720
        virtio_scsi_bad_req();
    }

721
    evt = &req->resp.event;
722
    memset(evt, 0, sizeof(VirtIOSCSIEvent));
723 724
    evt->event = virtio_tswap32(vdev, event);
    evt->reason = virtio_tswap32(vdev, reason);
725
    if (!dev) {
726
        assert(event == VIRTIO_SCSI_T_EVENTS_MISSED);
727
    } else {
728 729 730 731 732 733 734 735
        evt->lun[0] = 1;
        evt->lun[1] = dev->id;

        /* Linux wants us to keep the same encoding we use for REPORT LUNS.  */
        if (dev->lun >= 256) {
            evt->lun[2] = (dev->lun >> 8) | 0x40;
        }
        evt->lun[3] = dev->lun & 0xFF;
736 737
    }
    virtio_scsi_complete_req(req);
F
Fam Zheng 已提交
738 739 740 741
out:
    if (s->dataplane_started) {
        aio_context_release(s->ctx);
    }
742 743
}

744 745 746 747 748 749 750
void virtio_scsi_handle_event_vq(VirtIOSCSI *s, VirtQueue *vq)
{
    if (s->events_dropped) {
        virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
    }
}

751 752
static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
{
753
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
754

755
    if (s->ctx) {
F
Fam Zheng 已提交
756
        virtio_scsi_dataplane_start(s);
757 758 759
        if (!s->dataplane_fenced) {
            return;
        }
760
    }
761
    virtio_scsi_handle_event_vq(s, vq);
762 763
}

764 765 766
static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
{
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
767
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
768

769
    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
770 771 772 773 774 775
        dev->type != TYPE_ROM) {
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
                               sense.asc | (sense.ascq << 8));
    }
}

776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
static void virtio_scsi_blk_insert_notifier(Notifier *n, void *data)
{
    VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
                                                n, n);
    assert(cn->sd->conf.blk == data);
    blk_op_block_all(cn->sd->conf.blk, cn->s->blocker);
}

static void virtio_scsi_blk_remove_notifier(Notifier *n, void *data)
{
    VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
                                                n, n);
    assert(cn->sd->conf.blk == data);
    blk_op_unblock_all(cn->sd->conf.blk, cn->s->blocker);
}

792 793
static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp)
794
{
795
    VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
F
Fam Zheng 已提交
796 797 798
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
    SCSIDevice *sd = SCSI_DEVICE(dev);

P
Paolo Bonzini 已提交
799
    if (s->ctx && !s->dataplane_fenced) {
800 801
        VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;

F
Fam Zheng 已提交
802 803 804 805
        if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
            return;
        }
        blk_op_block_all(sd->conf.blk, s->blocker);
806 807 808
        aio_context_acquire(s->ctx);
        blk_set_aio_context(sd->conf.blk, s->ctx);
        aio_context_release(s->ctx);
809 810 811 812 813 814 815 816 817 818 819 820 821 822

        insert_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
        insert_notifier->n.notify = virtio_scsi_blk_insert_notifier;
        insert_notifier->s = s;
        insert_notifier->sd = sd;
        blk_add_insert_bs_notifier(sd->conf.blk, &insert_notifier->n);
        QTAILQ_INSERT_TAIL(&s->insert_notifiers, insert_notifier, next);

        remove_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
        remove_notifier->n.notify = virtio_scsi_blk_remove_notifier;
        remove_notifier->s = s;
        remove_notifier->sd = sd;
        blk_add_remove_bs_notifier(sd->conf.blk, &remove_notifier->n);
        QTAILQ_INSERT_TAIL(&s->remove_notifiers, remove_notifier, next);
F
Fam Zheng 已提交
823
    }
824

825
    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
F
Fam Zheng 已提交
826
        virtio_scsi_push_event(s, sd,
827
                               VIRTIO_SCSI_T_TRANSPORT_RESET,
828 829 830 831
                               VIRTIO_SCSI_EVT_RESET_RESCAN);
    }
}

832 833
static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                  Error **errp)
834
{
835
    VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
F
Fam Zheng 已提交
836 837
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
    SCSIDevice *sd = SCSI_DEVICE(dev);
838
    VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;
839

840
    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
F
Fam Zheng 已提交
841
        virtio_scsi_push_event(s, sd,
842
                               VIRTIO_SCSI_T_TRANSPORT_RESET,
843 844
                               VIRTIO_SCSI_EVT_RESET_REMOVED);
    }
F
Fam Zheng 已提交
845 846 847 848

    if (s->ctx) {
        blk_op_unblock_all(sd->conf.blk, s->blocker);
    }
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867

    QTAILQ_FOREACH(insert_notifier, &s->insert_notifiers, next) {
        if (insert_notifier->sd == sd) {
            notifier_remove(&insert_notifier->n);
            QTAILQ_REMOVE(&s->insert_notifiers, insert_notifier, next);
            g_free(insert_notifier);
            break;
        }
    }

    QTAILQ_FOREACH(remove_notifier, &s->remove_notifiers, next) {
        if (remove_notifier->sd == sd) {
            notifier_remove(&remove_notifier->n);
            QTAILQ_REMOVE(&s->remove_notifiers, remove_notifier, next);
            g_free(remove_notifier);
            break;
        }
    }

868
    qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
869 870
}

871 872 873 874 875 876 877 878
static struct SCSIBusInfo virtio_scsi_scsi_info = {
    .tcq = true,
    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
    .max_target = VIRTIO_SCSI_MAX_TARGET,
    .max_lun = VIRTIO_SCSI_MAX_LUN,

    .complete = virtio_scsi_command_complete,
    .cancel = virtio_scsi_request_cancelled,
879
    .change = virtio_scsi_change,
P
Paolo Bonzini 已提交
880
    .parse_cdb = virtio_scsi_parse_cdb,
881
    .get_sg_list = virtio_scsi_get_sg_list,
882 883
    .save_request = virtio_scsi_save_request,
    .load_request = virtio_scsi_load_request,
884 885
};

886 887 888
void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
                                HandleOutput ctrl, HandleOutput evt,
                                HandleOutput cmd)
889
{
890 891
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
892
    int i;
893

894
    virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
895
                sizeof(VirtIOSCSIConfig));
896

897
    if (s->conf.num_queues == 0 ||
898
            s->conf.num_queues > VIRTIO_QUEUE_MAX - 2) {
899
        error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
900
                         "must be a positive integer less than %d.",
901
                   s->conf.num_queues, VIRTIO_QUEUE_MAX - 2);
902
        virtio_cleanup(vdev);
903 904
        return;
    }
905
    s->cmd_vqs = g_new0(VirtQueue *, s->conf.num_queues);
906 907
    s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
    s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
908

909
    s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
910
                                  ctrl);
911
    s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
912
                                   evt);
913
    for (i = 0; i < s->conf.num_queues; i++) {
914
        s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
915
                                         cmd);
916
    }
917 918 919 920

    if (s->conf.iothread) {
        virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
    }
921 922
}

923
static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
924
{
925
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
926
    VirtIOSCSI *s = VIRTIO_SCSI(dev);
927
    static int virtio_scsi_id;
928
    Error *err = NULL;
929

930 931 932
    virtio_scsi_common_realize(dev, &err, virtio_scsi_handle_ctrl,
                               virtio_scsi_handle_event,
                               virtio_scsi_handle_cmd);
933 934 935
    if (err != NULL) {
        error_propagate(errp, err);
        return;
936 937
    }

938
    scsi_bus_new(&s->bus, sizeof(s->bus), dev,
939
                 &virtio_scsi_scsi_info, vdev->bus_name);
940 941
    /* override default SCSI bus hotplug-handler, with virtio-scsi's one */
    qbus_set_hotplug_handler(BUS(&s->bus), dev, &error_abort);
942

943
    if (!dev->hotplugged) {
944 945
        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
        if (err != NULL) {
946 947
            error_propagate(errp, err);
            return;
948
        }
949 950
    }

951
    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
952
                    virtio_scsi_save, virtio_scsi_load, s);
953 954

    error_setg(&s->blocker, "block device is in use by data plane");
955 956 957

    QTAILQ_INIT(&s->insert_notifiers);
    QTAILQ_INIT(&s->remove_notifiers);
958 959
}

960 961 962 963 964 965 966 967 968 969
static void virtio_scsi_instance_init(Object *obj)
{
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(obj);

    object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
                             (Object **)&vs->conf.iothread,
                             qdev_prop_allow_set_link_before_realize,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
}

970
void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
971
{
972 973
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
974 975

    g_free(vs->cmd_vqs);
976
    virtio_cleanup(vdev);
977 978
}

979
static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
980
{
981 982
    VirtIOSCSI *s = VIRTIO_SCSI(dev);

983 984
    error_free(s->blocker);

985 986
    unregister_savevm(dev, "virtio-scsi", s);
    virtio_scsi_common_unrealize(dev, errp);
987 988 989
}

static Property virtio_scsi_properties[] = {
990 991 992 993 994 995 996 997 998
    DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
    DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
                                                  0xFFFF),
    DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
                                                  128),
    DEFINE_PROP_BIT("hotplug", VirtIOSCSI, host_features,
                                           VIRTIO_SCSI_F_HOTPLUG, true),
    DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features,
                                                VIRTIO_SCSI_F_CHANGE, true),
999 1000 1001
    DEFINE_PROP_END_OF_LIST(),
};

1002 1003 1004
static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
{
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1005
    DeviceClass *dc = DEVICE_CLASS(klass);
1006 1007

    vdc->get_config = virtio_scsi_get_config;
1008
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1009 1010
}

1011 1012 1013 1014
static void virtio_scsi_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1015
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
1016

1017
    dc->props = virtio_scsi_properties;
1018
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1019
    vdc->realize = virtio_scsi_device_realize;
1020
    vdc->unrealize = virtio_scsi_device_unrealize;
1021 1022 1023
    vdc->set_config = virtio_scsi_set_config;
    vdc->get_features = virtio_scsi_get_features;
    vdc->reset = virtio_scsi_reset;
1024 1025
    hc->plug = virtio_scsi_hotplug;
    hc->unplug = virtio_scsi_hotunplug;
1026 1027
}

1028 1029 1030 1031
static const TypeInfo virtio_scsi_common_info = {
    .name = TYPE_VIRTIO_SCSI_COMMON,
    .parent = TYPE_VIRTIO_DEVICE,
    .instance_size = sizeof(VirtIOSCSICommon),
1032
    .abstract = true,
1033 1034 1035
    .class_init = virtio_scsi_common_class_init,
};

1036 1037
static const TypeInfo virtio_scsi_info = {
    .name = TYPE_VIRTIO_SCSI,
1038
    .parent = TYPE_VIRTIO_SCSI_COMMON,
1039
    .instance_size = sizeof(VirtIOSCSI),
1040
    .instance_init = virtio_scsi_instance_init,
1041
    .class_init = virtio_scsi_class_init,
1042 1043 1044 1045
    .interfaces = (InterfaceInfo[]) {
        { TYPE_HOTPLUG_HANDLER },
        { }
    }
1046 1047 1048 1049
};

static void virtio_register_types(void)
{
1050
    type_register_static(&virtio_scsi_common_info);
1051 1052 1053 1054
    type_register_static(&virtio_scsi_info);
}

type_init(virtio_register_types)