qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands
@ 2014-07-11  8:53 TAMUKI Shoichi
  2014-07-11  9:02 ` Paolo Bonzini
  0 siblings, 1 reply; 3+ messages in thread
From: TAMUKI Shoichi @ 2014-07-11  8:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, tamuki

Currently, some special SCSI commands sent from the initiator in a
guest do not reach the target device.  To avoid this, extended (0x7e,)
variable length (0x7f,) and vendor specific (0xc0..0xff) opcodes are
now treated as valid CDBs.

Originally, the most significant 3 bits of a SCSI opcode specified the
length of the CDB.  However, when variable-length CDBs were created,
this correspondence was changed, and the entire opcode must be
examined to determine the CDB length.  The CDBs with the opcodes above
are done that way for now.

Signed-off-by: TAMUKI Shoichi <tamuki@linet.gr.jp>
---
 hw/scsi/scsi-bus.c              | 21 ++++++++++++++++++---
 hw/scsi/virtio-scsi.c           | 25 -------------------------
 include/hw/virtio/virtio-scsi.h | 25 +++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ea1ac09..c631ebd 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -6,10 +6,12 @@
 #include "sysemu/blockdev.h"
 #include "trace.h"
 #include "sysemu/dma.h"
+#include "hw/virtio/virtio-scsi.h"
 
 static char *scsibus_get_dev_path(DeviceState *dev);
 static char *scsibus_get_fw_dev_path(DeviceState *dev);
-static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
+static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf,
+        uint32_t len);
 static void scsi_req_dequeue(SCSIRequest *req);
 static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
 static void scsi_target_free_buf(SCSIRequest *req);
@@ -563,7 +565,8 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
     SCSIRequest *req;
     SCSICommand cmd;
 
-    if (scsi_req_parse(&cmd, d, buf) != 0) {
+    if (scsi_req_parse(&cmd, d, buf,
+            ((VirtIOSCSIReq *) hba_private)->dev->parent_obj.cdb_size) != 0) {
         trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
         req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
     } else {
@@ -1181,7 +1184,8 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
     return lba;
 }
 
-static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
+static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf,
+        uint32_t len)
 {
     int rc;
 
@@ -1193,12 +1197,23 @@ static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case 2:
         cmd->len = 10;
         break;
+    case 3:
+        if (buf[0] == 0x7e || (buf[0] == 0x7f && len >= 16)) {
+            cmd->len = len;
+        } else {
+            return -1;
+        }
+        break;
     case 4:
         cmd->len = 16;
         break;
     case 5:
         cmd->len = 12;
         break;
+    case 6:
+    case 7:
+        cmd->len = len;
+        break;
     default:
         return -1;
     }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 0eb069a..c5710aa 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -21,31 +21,6 @@
 #include <hw/virtio/virtio-bus.h>
 #include "hw/virtio/virtio-access.h"
 
-typedef struct VirtIOSCSIReq {
-    VirtIOSCSI *dev;
-    VirtQueue *vq;
-    VirtQueueElement elem;
-    QEMUSGList qsgl;
-    SCSIRequest *sreq;
-    size_t resp_size;
-    enum SCSIXferMode mode;
-    QEMUIOVector resp_iov;
-    union {
-        VirtIOSCSICmdResp     cmd;
-        VirtIOSCSICtrlTMFResp tmf;
-        VirtIOSCSICtrlANResp  an;
-        VirtIOSCSIEvent       event;
-    } resp;
-    union {
-        struct {
-            VirtIOSCSICmdReq  cmd;
-            uint8_t           cdb[];
-        } QEMU_PACKED;
-        VirtIOSCSICtrlTMFReq  tmf;
-        VirtIOSCSICtrlANReq   an;
-    } req;
-} VirtIOSCSIReq;
-
 QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) !=
                   offsetof(VirtIOSCSIReq, req.cmd) + sizeof(VirtIOSCSICmdReq));
 
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 0419ee4..fae3f81 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -172,6 +172,31 @@ typedef struct {
     bool events_dropped;
 } VirtIOSCSI;
 
+typedef struct VirtIOSCSIReq {
+    VirtIOSCSI *dev;
+    VirtQueue *vq;
+    VirtQueueElement elem;
+    QEMUSGList qsgl;
+    SCSIRequest *sreq;
+    size_t resp_size;
+    enum SCSIXferMode mode;
+    QEMUIOVector resp_iov;
+    union {
+        VirtIOSCSICmdResp     cmd;
+        VirtIOSCSICtrlTMFResp tmf;
+        VirtIOSCSICtrlANResp  an;
+        VirtIOSCSIEvent       event;
+    } resp;
+    union {
+        struct {
+            VirtIOSCSICmdReq  cmd;
+            uint8_t           cdb[];
+        } QEMU_PACKED;
+        VirtIOSCSICtrlTMFReq  tmf;
+        VirtIOSCSICtrlANReq   an;
+    } req;
+} VirtIOSCSIReq;
+
 #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field)                     \
     DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1),       \
     DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-07-12 10:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-11  8:53 [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands TAMUKI Shoichi
2014-07-11  9:02 ` Paolo Bonzini
2014-07-12 10:21   ` TAMUKI Shoichi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).