qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

virtio-scsi.c (14286B)


      1 /*
      2  * Virtio-SCSI implementation for s390 machine loader for qemu
      3  *
      4  * Copyright 2015 IBM Corp.
      5  * Author: Eugene "jno" Dvurechenski <jno@linux.vnet.ibm.com>
      6  *
      7  * This work is licensed under the terms of the GNU GPL, version 2 or (at
      8  * your option) any later version. See the COPYING file in the top-level
      9  * directory.
     10  */
     11 
     12 #include "libc.h"
     13 #include "s390-ccw.h"
     14 #include "virtio.h"
     15 #include "scsi.h"
     16 #include "virtio-scsi.h"
     17 #include "s390-time.h"
     18 #include "helper.h"
     19 
     20 static ScsiDevice default_scsi_device;
     21 static VirtioScsiCmdReq req;
     22 static VirtioScsiCmdResp resp;
     23 
     24 static uint8_t scsi_inquiry_std_response[256];
     25 static ScsiInquiryEvpdPages scsi_inquiry_evpd_pages_response;
     26 static ScsiInquiryEvpdBl scsi_inquiry_evpd_bl_response;
     27 
     28 static inline void vs_assert(bool term, const char **msgs)
     29 {
     30     if (!term) {
     31         int i = 0;
     32 
     33         sclp_print("\n! ");
     34         while (msgs[i]) {
     35             sclp_print(msgs[i++]);
     36         }
     37         panic(" !\n");
     38     }
     39 }
     40 
     41 static void virtio_scsi_verify_response(VirtioScsiCmdResp *resp,
     42                                         const char *title)
     43 {
     44     const char *mr[] = {
     45         title, ": response ", virtio_scsi_response_msg(resp), 0
     46     };
     47     const char *ms[] = {
     48         title,
     49         CDB_STATUS_VALID(resp->status) ? ": " : ": invalid ",
     50         scsi_cdb_status_msg(resp->status),
     51         resp->status == CDB_STATUS_CHECK_CONDITION ? " " : 0,
     52         resp->sense_len ? scsi_cdb_asc_msg(resp->sense)
     53                         : "no sense data",
     54         scsi_sense_response(resp->sense)  == 0x70 ? ", sure" : "?",
     55         0
     56     };
     57 
     58     vs_assert(resp->response == VIRTIO_SCSI_S_OK, mr);
     59     vs_assert(resp->status == CDB_STATUS_GOOD, ms);
     60 }
     61 
     62 static void prepare_request(VDev *vdev, const void *cdb, int cdb_size,
     63                             void *data, uint32_t data_size)
     64 {
     65     const ScsiDevice *sdev = vdev->scsi_device;
     66 
     67     memset(&req, 0, sizeof(req));
     68     req.lun = make_lun(sdev->channel, sdev->target, sdev->lun);
     69     memcpy(&req.cdb, cdb, cdb_size);
     70 
     71     memset(&resp, 0, sizeof(resp));
     72     resp.status = 0xff;     /* set invalid  */
     73     resp.response = 0xff;   /*              */
     74 
     75     if (data && data_size) {
     76         memset(data, 0, data_size);
     77     }
     78 }
     79 
     80 static inline void vs_io_assert(bool term, const char *msg)
     81 {
     82     if (!term) {
     83         virtio_scsi_verify_response(&resp, msg);
     84     }
     85 }
     86 
     87 static void vs_run(const char *title, VirtioCmd *cmd, VDev *vdev,
     88                    const void *cdb, int cdb_size,
     89                    void *data, uint32_t data_size)
     90 {
     91     prepare_request(vdev, cdb, cdb_size, data, data_size);
     92     vs_io_assert(virtio_run(vdev, VR_REQUEST, cmd) == 0, title);
     93 }
     94 
     95 /* SCSI protocol implementation routines */
     96 
     97 static bool scsi_inquiry(VDev *vdev, uint8_t evpd, uint8_t page,
     98                          void *data, uint32_t data_size)
     99 {
    100     ScsiCdbInquiry cdb = {
    101         .command = 0x12,
    102         .b1 = evpd,
    103         .b2 = page,
    104         .alloc_len = data_size < 65535 ? data_size : 65535,
    105     };
    106     VirtioCmd inquiry[] = {
    107         { &req, sizeof(req), VRING_DESC_F_NEXT },
    108         { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
    109         { data, data_size, VRING_DESC_F_WRITE },
    110     };
    111 
    112     vs_run("inquiry", inquiry, vdev, &cdb, sizeof(cdb), data, data_size);
    113 
    114     return virtio_scsi_response_ok(&resp);
    115 }
    116 
    117 static bool scsi_test_unit_ready(VDev *vdev)
    118 {
    119     ScsiCdbTestUnitReady cdb = {
    120         .command = 0x00,
    121     };
    122     VirtioCmd test_unit_ready[] = {
    123         { &req, sizeof(req), VRING_DESC_F_NEXT },
    124         { &resp, sizeof(resp), VRING_DESC_F_WRITE },
    125     };
    126 
    127     prepare_request(vdev, &cdb, sizeof(cdb), 0, 0);
    128     virtio_run(vdev, VR_REQUEST, test_unit_ready); /* ignore errors here */
    129 
    130     return virtio_scsi_response_ok(&resp);
    131 }
    132 
    133 static bool scsi_report_luns(VDev *vdev, void *data, uint32_t data_size)
    134 {
    135     ScsiCdbReportLuns cdb = {
    136         .command = 0xa0,
    137         .select_report = 0x02, /* REPORT ALL */
    138         .alloc_len = data_size,
    139     };
    140     VirtioCmd report_luns[] = {
    141         { &req, sizeof(req), VRING_DESC_F_NEXT },
    142         { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
    143         { data, data_size, VRING_DESC_F_WRITE },
    144     };
    145 
    146     vs_run("report luns", report_luns,
    147            vdev, &cdb, sizeof(cdb), data, data_size);
    148 
    149     return virtio_scsi_response_ok(&resp);
    150 }
    151 
    152 static bool scsi_read_10(VDev *vdev,
    153                          ulong sector, int sectors, void *data,
    154                          unsigned int data_size)
    155 {
    156     ScsiCdbRead10 cdb = {
    157         .command = 0x28,
    158         .lba = sector,
    159         .xfer_length = sectors,
    160     };
    161     VirtioCmd read_10[] = {
    162         { &req, sizeof(req), VRING_DESC_F_NEXT },
    163         { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
    164         { data, data_size, VRING_DESC_F_WRITE },
    165     };
    166 
    167     debug_print_int("read_10  sector", sector);
    168     debug_print_int("read_10 sectors", sectors);
    169 
    170     vs_run("read(10)", read_10, vdev, &cdb, sizeof(cdb), data, data_size);
    171 
    172     return virtio_scsi_response_ok(&resp);
    173 }
    174 
    175 static bool scsi_read_capacity(VDev *vdev,
    176                                void *data, uint32_t data_size)
    177 {
    178     ScsiCdbReadCapacity16 cdb = {
    179         .command = 0x9e, /* SERVICE_ACTION_IN_16 */
    180         .service_action = 0x10, /* SA_READ_CAPACITY */
    181         .alloc_len = data_size,
    182     };
    183     VirtioCmd read_capacity_16[] = {
    184         { &req, sizeof(req), VRING_DESC_F_NEXT },
    185         { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
    186         { data, data_size, VRING_DESC_F_WRITE },
    187     };
    188 
    189     vs_run("read capacity", read_capacity_16,
    190            vdev, &cdb, sizeof(cdb), data, data_size);
    191 
    192     return virtio_scsi_response_ok(&resp);
    193 }
    194 
    195 /* virtio-scsi routines */
    196 
    197 /*
    198  * Tries to locate a SCSI device and adds the information for the found
    199  * device to the vdev->scsi_device structure.
    200  * Returns 0 if SCSI device could be located, or a error code < 0 otherwise
    201  */
    202 static int virtio_scsi_locate_device(VDev *vdev)
    203 {
    204     const uint16_t channel = 0; /* again, it's what QEMU does */
    205     uint16_t target;
    206     static uint8_t data[16 + 8 * 63];
    207     ScsiLunReport *r = (void *) data;
    208     ScsiDevice *sdev = vdev->scsi_device;
    209     int i, luns;
    210 
    211     /* QEMU has hardcoded channel #0 in many places.
    212      * If this hardcoded value is ever changed, we'll need to add code for
    213      * vdev->config.scsi.max_channel != 0 here.
    214      */
    215     debug_print_int("config.scsi.max_channel", vdev->config.scsi.max_channel);
    216     debug_print_int("config.scsi.max_target ", vdev->config.scsi.max_target);
    217     debug_print_int("config.scsi.max_lun    ", vdev->config.scsi.max_lun);
    218     debug_print_int("config.scsi.max_sectors", vdev->config.scsi.max_sectors);
    219 
    220     if (vdev->scsi_device_selected) {
    221         sdev->channel = vdev->selected_scsi_device.channel;
    222         sdev->target = vdev->selected_scsi_device.target;
    223         sdev->lun = vdev->selected_scsi_device.lun;
    224 
    225         IPL_check(sdev->channel == 0, "non-zero channel requested");
    226         IPL_check(sdev->target <= vdev->config.scsi.max_target, "target# high");
    227         IPL_check(sdev->lun <= vdev->config.scsi.max_lun, "LUN# high");
    228         return 0;
    229     }
    230 
    231     for (target = 0; target <= vdev->config.scsi.max_target; target++) {
    232         sdev->channel = channel;
    233         sdev->target = target;
    234         sdev->lun = 0;          /* LUN has to be 0 for REPORT LUNS */
    235         if (!scsi_report_luns(vdev, data, sizeof(data))) {
    236             if (resp.response == VIRTIO_SCSI_S_BAD_TARGET) {
    237                 continue;
    238             }
    239             print_int("target", target);
    240             virtio_scsi_verify_response(&resp, "SCSI cannot report LUNs");
    241         }
    242         if (r->lun_list_len == 0) {
    243             print_int("no LUNs for target", target);
    244             continue;
    245         }
    246         luns = r->lun_list_len / 8;
    247         debug_print_int("LUNs reported", luns);
    248         if (luns == 1) {
    249             /* There is no ",lun=#" arg for -device or ",lun=0" given.
    250              * Hence, the only LUN reported.
    251              * Usually, it's 0.
    252              */
    253             sdev->lun = r->lun[0].v16[0]; /* it's returned this way */
    254             debug_print_int("Have to use LUN", sdev->lun);
    255             return 0; /* we have to use this device */
    256         }
    257         for (i = 0; i < luns; i++) {
    258             if (r->lun[i].v64) {
    259                 /* Look for non-zero LUN - we have where to choose from */
    260                 sdev->lun = r->lun[i].v16[0];
    261                 debug_print_int("Will use LUN", sdev->lun);
    262                 return 0; /* we have found a device */
    263             }
    264         }
    265     }
    266 
    267     sclp_print("Warning: Could not locate a usable virtio-scsi device\n");
    268     return -ENODEV;
    269 }
    270 
    271 int virtio_scsi_read_many(VDev *vdev,
    272                           ulong sector, void *load_addr, int sec_num)
    273 {
    274     int sector_count;
    275     int f = vdev->blk_factor;
    276     unsigned int data_size;
    277     unsigned int max_transfer = MIN_NON_ZERO(vdev->config.scsi.max_sectors,
    278                                              vdev->max_transfer);
    279 
    280     do {
    281         sector_count = MIN_NON_ZERO(sec_num, max_transfer);
    282         data_size = sector_count * virtio_get_block_size() * f;
    283         if (!scsi_read_10(vdev, sector * f, sector_count * f, load_addr,
    284                           data_size)) {
    285             virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
    286         }
    287         load_addr += data_size;
    288         sector += sector_count;
    289         sec_num -= sector_count;
    290     } while (sec_num > 0);
    291 
    292     return 0;
    293 }
    294 
    295 static bool virtio_scsi_inquiry_response_is_cdrom(void *data)
    296 {
    297     const ScsiInquiryStd *response = data;
    298     const int resp_data_fmt = response->b3 & 0x0f;
    299     int i;
    300 
    301     IPL_check(resp_data_fmt == 2, "Wrong INQUIRY response format");
    302     if (resp_data_fmt != 2) {
    303         return false; /* cannot decode */
    304     }
    305 
    306     if ((response->peripheral_qdt & 0x1f) == SCSI_INQ_RDT_CDROM) {
    307         return true;
    308     }
    309 
    310     for (i = 0; i < sizeof(response->prod_id); i++) {
    311         if (response->prod_id[i] != QEMU_CDROM_SIGNATURE[i]) {
    312             return false;
    313         }
    314     }
    315     return true;
    316 }
    317 
    318 static void scsi_parse_capacity_report(void *data,
    319                                        uint64_t *last_lba, uint32_t *lb_len)
    320 {
    321     ScsiReadCapacity16Data *p = data;
    322 
    323     if (last_lba) {
    324         *last_lba = p->ret_lba;
    325     }
    326 
    327     if (lb_len) {
    328         *lb_len = p->lb_len;
    329     }
    330 }
    331 
    332 static int virtio_scsi_setup(VDev *vdev)
    333 {
    334     int retry_test_unit_ready = 3;
    335     uint8_t data[256];
    336     uint32_t data_size = sizeof(data);
    337     ScsiInquiryEvpdPages *evpd = &scsi_inquiry_evpd_pages_response;
    338     ScsiInquiryEvpdBl *evpd_bl = &scsi_inquiry_evpd_bl_response;
    339     int i, ret;
    340 
    341     vdev->scsi_device = &default_scsi_device;
    342     ret = virtio_scsi_locate_device(vdev);
    343     if (ret < 0) {
    344         return ret;
    345     }
    346 
    347     /* We have to "ping" the device before it becomes readable */
    348     while (!scsi_test_unit_ready(vdev)) {
    349 
    350         if (!virtio_scsi_response_ok(&resp)) {
    351             uint8_t code = resp.sense[0] & SCSI_SENSE_CODE_MASK;
    352             uint8_t sense_key = resp.sense[2] & SCSI_SENSE_KEY_MASK;
    353 
    354             IPL_assert(resp.sense_len != 0, "virtio-scsi:setup: no SENSE data");
    355 
    356             IPL_assert(retry_test_unit_ready && code == 0x70 &&
    357                        sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION,
    358                        "virtio-scsi:setup: cannot retry");
    359 
    360             /* retry on CHECK_CONDITION/UNIT_ATTENTION as it
    361              * may not designate a real error, but it may be
    362              * a result of device reset, etc.
    363              */
    364             retry_test_unit_ready--;
    365             sleep(1);
    366             continue;
    367         }
    368 
    369         virtio_scsi_verify_response(&resp, "virtio-scsi:setup");
    370     }
    371 
    372     /* read and cache SCSI INQUIRY response */
    373     if (!scsi_inquiry(vdev,
    374                       SCSI_INQUIRY_STANDARD,
    375                       SCSI_INQUIRY_STANDARD_NONE,
    376                       scsi_inquiry_std_response,
    377                       sizeof(scsi_inquiry_std_response))) {
    378         virtio_scsi_verify_response(&resp, "virtio-scsi:setup:inquiry");
    379     }
    380 
    381     if (virtio_scsi_inquiry_response_is_cdrom(scsi_inquiry_std_response)) {
    382         sclp_print("SCSI CD-ROM detected.\n");
    383         vdev->is_cdrom = true;
    384         vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE;
    385     }
    386 
    387     if (!scsi_inquiry(vdev,
    388                       SCSI_INQUIRY_EVPD,
    389                       SCSI_INQUIRY_EVPD_SUPPORTED_PAGES,
    390                       evpd,
    391                       sizeof(*evpd))) {
    392         virtio_scsi_verify_response(&resp, "virtio-scsi:setup:supported_pages");
    393     }
    394 
    395     debug_print_int("EVPD length", evpd->page_length);
    396 
    397     for (i = 0; i <= evpd->page_length; i++) {
    398         debug_print_int("supported EVPD page", evpd->byte[i]);
    399 
    400         if (evpd->byte[i] != SCSI_INQUIRY_EVPD_BLOCK_LIMITS) {
    401             continue;
    402         }
    403 
    404         if (!scsi_inquiry(vdev,
    405                           SCSI_INQUIRY_EVPD,
    406                           SCSI_INQUIRY_EVPD_BLOCK_LIMITS,
    407                           evpd_bl,
    408                           sizeof(*evpd_bl))) {
    409             virtio_scsi_verify_response(&resp, "virtio-scsi:setup:blocklimits");
    410         }
    411 
    412         debug_print_int("max transfer", evpd_bl->max_transfer);
    413         vdev->max_transfer = evpd_bl->max_transfer;
    414     }
    415 
    416     /*
    417      * The host sg driver will often be unhappy with particularly large
    418      * I/Os that exceed the block iovec limits.  Let's enforce something
    419      * reasonable, despite what the device configuration tells us.
    420      */
    421 
    422     vdev->max_transfer = MIN_NON_ZERO(VIRTIO_SCSI_MAX_SECTORS,
    423                                       vdev->max_transfer);
    424 
    425     if (!scsi_read_capacity(vdev, data, data_size)) {
    426         virtio_scsi_verify_response(&resp, "virtio-scsi:setup:read_capacity");
    427     }
    428     scsi_parse_capacity_report(data, &vdev->scsi_last_block,
    429                                (uint32_t *) &vdev->scsi_block_size);
    430 
    431     return 0;
    432 }
    433 
    434 int virtio_scsi_setup_device(SubChannelId schid)
    435 {
    436     VDev *vdev = virtio_get_device();
    437 
    438     vdev->schid = schid;
    439     virtio_setup_ccw(vdev);
    440 
    441     IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE,
    442                "Config: sense size mismatch");
    443     IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE,
    444                "Config: CDB size mismatch");
    445 
    446     sclp_print("Using virtio-scsi.\n");
    447 
    448     return virtio_scsi_setup(vdev);
    449 }