From patchwork Fri Apr 6 17:11:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 895790 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HyvachHi"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40Hmgn4dPSz9s0y for ; Sat, 7 Apr 2018 03:21:09 +1000 (AEST) Received: from localhost ([::1]:40837 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f4V2x-0007DY-CK for incoming@patchwork.ozlabs.org; Fri, 06 Apr 2018 13:21:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36372) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f4Utr-0007wV-8h for qemu-devel@nongnu.org; Fri, 06 Apr 2018 13:11:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f4Utp-0007jJ-G3 for qemu-devel@nongnu.org; Fri, 06 Apr 2018 13:11:43 -0400 Received: from mail-wr0-x235.google.com ([2a00:1450:400c:c0c::235]:39562) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f4Utp-0007hZ-5q for qemu-devel@nongnu.org; Fri, 06 Apr 2018 13:11:41 -0400 Received: by mail-wr0-x235.google.com with SMTP id c24so2415266wrc.6 for ; Fri, 06 Apr 2018 10:11:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=oeegdLmQ/PIm2BYXrmpuKTzjBLlphGig40DpkNscQDc=; b=HyvachHim8/7QMGMI/GWD1O44ACz1tnoULEuIW0hACUd2aTMdv6HgYb/IAaLP63OoD X29xYxR12mC+79opdYK4/HNEkpkcNCvVYsULo1qFaU+htmogfA0by/trPnEDrbvJ6h3T YS4UNmXhekvmFnYfstn4hVOuLjsV3rgCyPOX7/mUgCcAf5hKqjGWdcvGpxSSr9kFw1XU LNn8N8xwHLRPPlGCIOS4IquFdG9fPcGZF/gir1ecrycdS+nzZU4KtqMjXU7A4yj6H6je LJJC0Jg82LKCO8QXncb7zAml4cm00NxDowbFMdSUq/zO3TMakcUCHwI3g0aY1JiVwAsm Q/EA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=oeegdLmQ/PIm2BYXrmpuKTzjBLlphGig40DpkNscQDc=; b=U85zfmvaNqC4WzRYsAcmVZHcjPV77n/A50CF3MPk4VBaSUKEDKJcZV+zEpVkZ0K60v /bmGusX6Ga+QN1Xmu8ik+p7SrJXCx5CfXBcL1UTGDIGqQFU1re/MJMVT0rMuGsXZSwY9 mT8WpnCNbP9ri8CjyBPohrVKg+g1DlaZB/SyyMeT06u7MQ2AqRZTv5DzPHLGYFo8/NPi Ph8UCKZYywBAgf2IsiRGZd3FgCtwy0gQHC539CxfVQsDoCdxsvWKSXmVmi0KnE4AxZ5J b+w5d9r/FfDcr9fIrZ4JxJEgjVWFGaeV/Unv9yi8RF5TcOKHPqGFJtCrdrKE1f7TioS0 LtdQ== X-Gm-Message-State: AElRT7HDCF0zlRnFo9Jfq9JZyqsM2HQSE5HAYxeW5W7lA6a1Aj/VozBL uO/uZwKs/WfXs5OTOd4MQUFe0WYt X-Google-Smtp-Source: AIpwx4+f+yvfP6ssiRpYR4KMbrlb+GB71G6B0Z0vTcHXWqzJOxMyVFpS2N4SKAxAH+6wpWNSysxJZg== X-Received: by 10.223.182.18 with SMTP id f18mr18066355wre.211.1523034699717; Fri, 06 Apr 2018 10:11:39 -0700 (PDT) Received: from 640k.lan (94-36-194-48.adsl-ull.clienti.tiscali.it. [94.36.194.48]) by smtp.gmail.com with ESMTPSA id 24sm16286180wrt.60.2018.04.06.10.11.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Apr 2018 10:11:38 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Fri, 6 Apr 2018 19:11:12 +0200 Message-Id: <1523034681-33787-12-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1523034681-33787-1-git-send-email-pbonzini@redhat.com> References: <1523034681-33787-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c0c::235 Subject: [Qemu-devel] [PULL 11/20] hw/scsi: support SCSI-2 passthrough without PI X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Daniel Henrique Barboza QEMU SCSI code makes assumptions about how the PROTECT and BYTCHK works in the protocol, denying support for PI (Protection Information) in case the guest OS requests it. However, in SCSI versions 2 and older, there is no PI concept in the protocol. This means that when dealing with such devices: - there is no PROTECT bit in byte 5 of the standard INQUIRY response. The whole byte is marked as "Reserved"; - there is no RDPROTECT in byte 2 of READ. We have 'Logical Unit Number' in this field instead; - there is no VRPROTECT in byte 2 of VERIFY. We have 'Logical Unit Number' in this field instead. This also means that the BYTCHK bit in this case is not related to PI. Since QEMU does not consider these changes, a SCSI passthrough using a SCSI-2 device will not work. It will mistake these fields with PI information and return Illegal Request SCSI SENSE thinking that the driver is asking for PI support. This patch fixes it by adding a new attribute called 'scsi_version' that is read from the standard INQUIRY response of passthrough devices. This allows for a version verification before applying conditions related to PI that doesn't apply for older versions. Reported-by: Dac Nguyen Signed-off-by: Daniel Henrique Barboza Message-Id: <20180327211451.14647-1-danielhb@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 2 +- hw/scsi/scsi-generic.c | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 9400b97..ded23d3 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -3041,7 +3041,7 @@ static Property scsi_block_properties[] = { DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false), DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, - 5), + -1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 1870085..381f04e 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -194,17 +194,40 @@ static void scsi_read_complete(void * opaque, int ret) r->buf[3] |= 0x80; } } - if (s->type == TYPE_DISK && - r->req.cmd.buf[0] == INQUIRY && - r->req.cmd.buf[2] == 0xb0) { - uint32_t max_transfer = - blk_get_max_transfer(s->conf.blk) / s->blocksize; - - assert(max_transfer); - stl_be_p(&r->buf[8], max_transfer); - /* Also take care of the opt xfer len. */ - stl_be_p(&r->buf[12], - MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); + if (r->req.cmd.buf[0] == INQUIRY) { + /* + * EVPD set to zero returns the standard INQUIRY data. + * + * Check if scsi_version is unset (-1) to avoid re-defining it + * each time an INQUIRY with standard data is received. + * scsi_version is initialized with -1 in scsi_generic_reset + * and scsi_disk_reset, making sure that we'll set the + * scsi_version after a reset. If the version field of the + * INQUIRY response somehow changes after a guest reboot, + * we'll be able to keep track of it. + * + * On SCSI-2 and older, first 3 bits of byte 2 is the + * ANSI-approved version, while on later versions the + * whole byte 2 contains the version. Check if we're dealing + * with a newer version and, in that case, assign the + * whole byte. + */ + if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) { + s->scsi_version = r->buf[2] & 0x07; + if (s->scsi_version > 2) { + s->scsi_version = r->buf[2]; + } + } + if (s->type == TYPE_DISK && r->req.cmd.buf[2] == 0xb0) { + uint32_t max_transfer = + blk_get_max_transfer(s->conf.blk) / s->blocksize; + + assert(max_transfer); + stl_be_p(&r->buf[8], max_transfer); + /* Also take care of the opt xfer len. */ + stl_be_p(&r->buf[12], + MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); + } } scsi_req_data(&r->req, len); scsi_req_unref(&r->req); @@ -550,6 +573,8 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) DPRINTF("block size %d\n", s->blocksize); + /* Only used by scsi-block, but initialize it nevertheless to be clean. */ + s->default_scsi_version = -1; scsi_generic_read_device_identification(s); }