qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

scsi-disk: allow customizing the SCSI version

We would like to have different behavior for passthrough devices
depending on the SCSI version they expose. To prepare for that,
allow the user of emulated devices to specify the desired SCSI
level, and adjust the emulation according to the property value.
The next patch will set the level for scsi-block and scsi-generic
devices.

Based on a patch by Daniel Henrique Barboza
<danielhb@linux.vnet.ibm.com>.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+27 -5
+24 -5
hw/scsi/scsi-disk.c
··· 825 825 * block characteristics VPD page by default. Not all of SPC-3 826 826 * is actually implemented, but we're good enough. 827 827 */ 828 - outbuf[2] = 5; 828 + outbuf[2] = s->qdev.default_scsi_version; 829 829 outbuf[3] = 2 | 0x10; /* Format 2, HiSup */ 830 830 831 831 if (buflen > 36) { ··· 2193 2193 case READ_12: 2194 2194 case READ_16: 2195 2195 DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len); 2196 - if (r->req.cmd.buf[1] & 0xe0) { 2196 + /* Protection information is not supported. For SCSI versions 2 and 2197 + * older (as determined by snooping the guest's INQUIRY commands), 2198 + * there is no RD/WR/VRPROTECT, so skip this check in these versions. 2199 + */ 2200 + if (s->qdev.scsi_version > 2 && (r->req.cmd.buf[1] & 0xe0)) { 2197 2201 goto illegal_request; 2198 2202 } 2199 2203 if (!check_lba_range(s, r->req.cmd.lba, len)) { ··· 2224 2228 * As far as DMA is concerned, we can treat it the same as a write; 2225 2229 * scsi_block_do_sgio will send VERIFY commands. 2226 2230 */ 2227 - if (r->req.cmd.buf[1] & 0xe0) { 2231 + if (s->qdev.scsi_version > 2 && (r->req.cmd.buf[1] & 0xe0)) { 2228 2232 goto illegal_request; 2229 2233 } 2230 2234 if (!check_lba_range(s, r->req.cmd.lba, len)) { ··· 2270 2274 /* reset tray statuses */ 2271 2275 s->tray_locked = 0; 2272 2276 s->tray_open = 0; 2277 + 2278 + s->qdev.scsi_version = s->qdev.default_scsi_version; 2273 2279 } 2274 2280 2275 2281 static void scsi_disk_resize_cb(void *opaque) ··· 2814 2820 static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf) 2815 2821 { 2816 2822 SCSIBlockReq *r = (SCSIBlockReq *)req; 2823 + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); 2824 + 2817 2825 r->cmd = req->cmd.buf[0]; 2818 2826 switch (r->cmd >> 5) { 2819 2827 case 0: ··· 2839 2847 abort(); 2840 2848 } 2841 2849 2842 - if (r->cdb1 & 0xe0) { 2843 - /* Protection information is not supported. */ 2850 + /* Protection information is not supported. For SCSI versions 2 and 2851 + * older (as determined by snooping the guest's INQUIRY commands), 2852 + * there is no RD/WR/VRPROTECT, so skip this check in these versions. 2853 + */ 2854 + if (s->qdev.scsi_version > 2 && (req->cmd.buf[1] & 0xe0)) { 2844 2855 scsi_check_condition(&r->req, SENSE_CODE(INVALID_FIELD)); 2845 2856 return 0; 2846 2857 } ··· 2952 2963 DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, 2953 2964 DEFAULT_MAX_IO_SIZE), 2954 2965 DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), 2966 + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, 2967 + 5), 2955 2968 DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), 2956 2969 DEFINE_PROP_END_OF_LIST(), 2957 2970 }; ··· 2997 3010 DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), 2998 3011 DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, 2999 3012 DEFAULT_MAX_IO_SIZE), 3013 + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, 3014 + 5), 3000 3015 DEFINE_PROP_END_OF_LIST(), 3001 3016 }; 3002 3017 ··· 3025 3040 DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), 3026 3041 DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false), 3027 3042 DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), 3043 + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, 3044 + 5), 3028 3045 DEFINE_PROP_END_OF_LIST(), 3029 3046 }; 3030 3047 ··· 3065 3082 DEFAULT_MAX_UNMAP_SIZE), 3066 3083 DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, 3067 3084 DEFAULT_MAX_IO_SIZE), 3085 + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, 3086 + 5), 3068 3087 DEFINE_PROP_END_OF_LIST(), 3069 3088 }; 3070 3089
+1
hw/scsi/scsi-generic.c
··· 474 474 { 475 475 SCSIDevice *s = SCSI_DEVICE(dev); 476 476 477 + s->scsi_version = s->default_scsi_version; 477 478 scsi_device_purge_requests(s, SENSE_CODE(RESET)); 478 479 } 479 480
+2
include/hw/scsi/scsi.h
··· 85 85 uint64_t max_lba; 86 86 uint64_t wwn; 87 87 uint64_t port_wwn; 88 + int scsi_version; 89 + int default_scsi_version; 88 90 }; 89 91 90 92 extern const VMStateDescription vmstate_scsi_device;