From patchwork Mon Jul 6 06:12:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278499 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F93CC433E5 for ; Mon, 6 Jul 2020 06:19:46 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CDE4620708 for ; Mon, 6 Jul 2020 06:19:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CDE4620708 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:54224 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKTh-00041t-4k for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:19:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60544) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNY-0000jU-Qd; Mon, 06 Jul 2020 02:13:24 -0400 Received: from charlie.dont.surf ([128.199.63.193]:57964) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNQ-0000uW-9s; Mon, 06 Jul 2020 02:13:24 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id 7A220BF7A1; Mon, 6 Jul 2020 06:13:11 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 01/18] hw/block/nvme: bump spec data structures to v1.3 Date: Mon, 6 Jul 2020 08:12:46 +0200 Message-Id: <20200706061303.246057-2-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add missing fields in the Identify Controller and Identify Namespace data structures to bring them in line with NVMe v1.3. This also adds data structures and defines for SGL support which requires a couple of trivial changes to the nvme block driver as well. Signed-off-by: Klaus Jensen Acked-by: Fam Zheng Reviewed-by: Maxim Levitsky --- block/nvme.c | 18 ++--- hw/block/nvme.c | 12 ++-- include/block/nvme.h | 156 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 154 insertions(+), 32 deletions(-) diff --git a/block/nvme.c b/block/nvme.c index 374e26891573..c1c4c07ac6cc 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -518,7 +518,7 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp) error_setg(errp, "Cannot map buffer for DMA"); goto out; } - cmd.prp1 = cpu_to_le64(iova); + cmd.dptr.prp1 = cpu_to_le64(iova); if (nvme_cmd_sync(bs, s->queues[0], &cmd)) { error_setg(errp, "Failed to identify controller"); @@ -629,7 +629,7 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error **errp) } cmd = (NvmeCmd) { .opcode = NVME_ADM_CMD_CREATE_CQ, - .prp1 = cpu_to_le64(q->cq.iova), + .dptr.prp1 = cpu_to_le64(q->cq.iova), .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0xFFFF)), .cdw11 = cpu_to_le32(0x3), }; @@ -640,7 +640,7 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error **errp) } cmd = (NvmeCmd) { .opcode = NVME_ADM_CMD_CREATE_SQ, - .prp1 = cpu_to_le64(q->sq.iova), + .dptr.prp1 = cpu_to_le64(q->sq.iova), .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0xFFFF)), .cdw11 = cpu_to_le32(0x1 | (n << 16)), }; @@ -988,16 +988,16 @@ try_map: case 0: abort(); case 1: - cmd->prp1 = pagelist[0]; - cmd->prp2 = 0; + cmd->dptr.prp1 = pagelist[0]; + cmd->dptr.prp2 = 0; break; case 2: - cmd->prp1 = pagelist[0]; - cmd->prp2 = pagelist[1]; + cmd->dptr.prp1 = pagelist[0]; + cmd->dptr.prp2 = pagelist[1]; break; default: - cmd->prp1 = pagelist[0]; - cmd->prp2 = cpu_to_le64(req->prp_list_iova + sizeof(uint64_t)); + cmd->dptr.prp1 = pagelist[0]; + cmd->dptr.prp2 = cpu_to_le64(req->prp_list_iova + sizeof(uint64_t)); break; } trace_nvme_cmd_map_qiov(s, cmd, req, qiov, entries); diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 1aee042d4cb2..71b388aa0e20 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -397,8 +397,8 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, NvmeRwCmd *rw = (NvmeRwCmd *)cmd; uint32_t nlb = le32_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); - uint64_t prp1 = le64_to_cpu(rw->prp1); - uint64_t prp2 = le64_to_cpu(rw->prp2); + uint64_t prp1 = le64_to_cpu(rw->dptr.prp1); + uint64_t prp2 = le64_to_cpu(rw->dptr.prp2); uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds; @@ -795,8 +795,8 @@ static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n) static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) { - uint64_t prp1 = le64_to_cpu(cmd->prp1); - uint64_t prp2 = le64_to_cpu(cmd->prp2); + uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); + uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); uint64_t timestamp = nvme_get_timestamp(n); @@ -834,8 +834,8 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) { uint16_t ret; uint64_t timestamp; - uint64_t prp1 = le64_to_cpu(cmd->prp1); - uint64_t prp2 = le64_to_cpu(cmd->prp2); + uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); + uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); ret = nvme_dma_write_prp(n, (uint8_t *)×tamp, sizeof(timestamp), prp1, prp2); diff --git a/include/block/nvme.h b/include/block/nvme.h index 1720ee1d5158..2a80d2a7ed89 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -377,15 +377,53 @@ enum NvmePmrmscMask { #define NVME_PMRMSC_SET_CBA(pmrmsc, val) \ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT) +enum NvmeSglDescriptorType { + NVME_SGL_DESCR_TYPE_DATA_BLOCK = 0x0, + NVME_SGL_DESCR_TYPE_BIT_BUCKET = 0x1, + NVME_SGL_DESCR_TYPE_SEGMENT = 0x2, + NVME_SGL_DESCR_TYPE_LAST_SEGMENT = 0x3, + NVME_SGL_DESCR_TYPE_KEYED_DATA_BLOCK = 0x4, + + NVME_SGL_DESCR_TYPE_VENDOR_SPECIFIC = 0xf, +}; + +enum NvmeSglDescriptorSubtype { + NVME_SGL_DESCR_SUBTYPE_ADDRESS = 0x0, +}; + +typedef struct NvmeSglDescriptor { + uint64_t addr; + uint32_t len; + uint8_t rsvd[3]; + uint8_t type; +} NvmeSglDescriptor; + +#define NVME_SGL_TYPE(type) ((type >> 4) & 0xf) +#define NVME_SGL_SUBTYPE(type) (type & 0xf) + +typedef union NvmeCmdDptr { + struct { + uint64_t prp1; + uint64_t prp2; + }; + + NvmeSglDescriptor sgl; +} NvmeCmdDptr; + +enum NvmePsdt { + PSDT_PRP = 0x0, + PSDT_SGL_MPTR_CONTIGUOUS = 0x1, + PSDT_SGL_MPTR_SGL = 0x2, +}; + typedef struct NvmeCmd { uint8_t opcode; - uint8_t fuse; + uint8_t flags; uint16_t cid; uint32_t nsid; uint64_t res1; uint64_t mptr; - uint64_t prp1; - uint64_t prp2; + NvmeCmdDptr dptr; uint32_t cdw10; uint32_t cdw11; uint32_t cdw12; @@ -394,6 +432,9 @@ typedef struct NvmeCmd { uint32_t cdw15; } NvmeCmd; +#define NVME_CMD_FLAGS_FUSE(flags) (flags & 0x3) +#define NVME_CMD_FLAGS_PSDT(flags) ((flags >> 6) & 0x3) + enum NvmeAdminCommands { NVME_ADM_CMD_DELETE_SQ = 0x00, NVME_ADM_CMD_CREATE_SQ = 0x01, @@ -493,8 +534,7 @@ typedef struct NvmeRwCmd { uint32_t nsid; uint64_t rsvd2; uint64_t mptr; - uint64_t prp1; - uint64_t prp2; + NvmeCmdDptr dptr; uint64_t slba; uint16_t nlb; uint16_t control; @@ -534,8 +574,7 @@ typedef struct NvmeDsmCmd { uint16_t cid; uint32_t nsid; uint64_t rsvd2[2]; - uint64_t prp1; - uint64_t prp2; + NvmeCmdDptr dptr; uint32_t nr; uint32_t attributes; uint32_t rsvd12[4]; @@ -599,6 +638,12 @@ enum NvmeStatusCodes { NVME_CMD_ABORT_MISSING_FUSE = 0x000a, NVME_INVALID_NSID = 0x000b, NVME_CMD_SEQ_ERROR = 0x000c, + NVME_INVALID_SGL_SEG_DESCR = 0x000d, + NVME_INVALID_NUM_SGL_DESCRS = 0x000e, + NVME_DATA_SGL_LEN_INVALID = 0x000f, + NVME_MD_SGL_LEN_INVALID = 0x0010, + NVME_SGL_DESCR_TYPE_INVALID = 0x0011, + NVME_INVALID_USE_OF_CMB = 0x0012, NVME_LBA_RANGE = 0x0080, NVME_CAP_EXCEEDED = 0x0081, NVME_NS_NOT_READY = 0x0082, @@ -687,7 +732,7 @@ enum NvmeSmartWarn { NVME_SMART_FAILED_VOLATILE_MEDIA = 1 << 4, }; -enum LogIdentifier { +enum NvmeLogIdentifier { NVME_LOG_ERROR_INFO = 0x01, NVME_LOG_SMART_INFO = 0x02, NVME_LOG_FW_SLOT_INFO = 0x03, @@ -711,6 +756,7 @@ enum { NVME_ID_CNS_NS = 0x0, NVME_ID_CNS_CTRL = 0x1, NVME_ID_CNS_NS_ACTIVE_LIST = 0x2, + NVME_ID_CNS_NS_DESCR_LIST = 0x3, }; typedef struct NvmeIdCtrl { @@ -723,7 +769,15 @@ typedef struct NvmeIdCtrl { uint8_t ieee[3]; uint8_t cmic; uint8_t mdts; - uint8_t rsvd255[178]; + uint16_t cntlid; + uint32_t ver; + uint32_t rtd3r; + uint32_t rtd3e; + uint32_t oaes; + uint32_t ctratt; + uint8_t rsvd100[12]; + uint8_t fguid[16]; + uint8_t rsvd128[128]; uint16_t oacs; uint8_t acl; uint8_t aerl; @@ -731,10 +785,28 @@ typedef struct NvmeIdCtrl { uint8_t lpa; uint8_t elpe; uint8_t npss; - uint8_t rsvd511[248]; + uint8_t avscc; + uint8_t apsta; + uint16_t wctemp; + uint16_t cctemp; + uint16_t mtfa; + uint32_t hmpre; + uint32_t hmmin; + uint8_t tnvmcap[16]; + uint8_t unvmcap[16]; + uint32_t rpmbs; + uint16_t edstt; + uint8_t dsto; + uint8_t fwug; + uint16_t kas; + uint16_t hctma; + uint16_t mntmt; + uint16_t mxtmt; + uint32_t sanicap; + uint8_t rsvd332[180]; uint8_t sqes; uint8_t cqes; - uint16_t rsvd515; + uint16_t maxcmd; uint32_t nn; uint16_t oncs; uint16_t fuses; @@ -742,8 +814,14 @@ typedef struct NvmeIdCtrl { uint8_t vwc; uint16_t awun; uint16_t awupf; - uint8_t rsvd703[174]; - uint8_t rsvd2047[1344]; + uint8_t nvscc; + uint8_t rsvd531; + uint16_t acwu; + uint8_t rsvd534[2]; + uint32_t sgls; + uint8_t rsvd540[228]; + uint8_t subnqn[256]; + uint8_t rsvd1024[1024]; NvmePSD psd[32]; uint8_t vs[1024]; } NvmeIdCtrl; @@ -769,6 +847,16 @@ enum NvmeIdCtrlOncs { #define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf) #define NVME_CTRL_CQES_MAX(cqes) (((cqes) >> 4) & 0xf) +#define NVME_CTRL_SGLS_SUPPORT_MASK (0x3 << 0) +#define NVME_CTRL_SGLS_SUPPORT_NO_ALIGN (0x1 << 0) +#define NVME_CTRL_SGLS_SUPPORT_DWORD_ALIGN (0x1 << 1) +#define NVME_CTRL_SGLS_KEYED (0x1 << 2) +#define NVME_CTRL_SGLS_BITBUCKET (0x1 << 16) +#define NVME_CTRL_SGLS_MPTR_CONTIGUOUS (0x1 << 17) +#define NVME_CTRL_SGLS_EXCESS_LENGTH (0x1 << 18) +#define NVME_CTRL_SGLS_MPTR_SGL (0x1 << 19) +#define NVME_CTRL_SGLS_ADDR_OFFSET (0x1 << 20) + typedef struct NvmeFeatureVal { uint32_t arbitration; uint32_t power_mgmt; @@ -791,6 +879,15 @@ typedef struct NvmeFeatureVal { #define NVME_INTC_THR(intc) (intc & 0xff) #define NVME_INTC_TIME(intc) ((intc >> 8) & 0xff) +#define NVME_TEMP_THSEL(temp) ((temp >> 20) & 0x3) +#define NVME_TEMP_THSEL_OVER 0x0 +#define NVME_TEMP_THSEL_UNDER 0x1 + +#define NVME_TEMP_TMPSEL(temp) ((temp >> 16) & 0xf) +#define NVME_TEMP_TMPSEL_COMPOSITE 0x0 + +#define NVME_TEMP_TMPTH(temp) ((temp >> 0) & 0xffff) + enum NvmeFeatureIds { NVME_ARBITRATION = 0x1, NVME_POWER_MANAGEMENT = 0x2, @@ -833,18 +930,43 @@ typedef struct NvmeIdNs { uint8_t mc; uint8_t dpc; uint8_t dps; - uint8_t nmic; uint8_t rescap; uint8_t fpi; uint8_t dlfeat; - - uint8_t res34[94]; + uint16_t nawun; + uint16_t nawupf; + uint16_t nacwu; + uint16_t nabsn; + uint16_t nabo; + uint16_t nabspf; + uint16_t noiob; + uint8_t nvmcap[16]; + uint8_t rsvd64[40]; + uint8_t nguid[16]; + uint64_t eui64; NvmeLBAF lbaf[16]; - uint8_t res192[192]; + uint8_t rsvd192[192]; uint8_t vs[3712]; } NvmeIdNs; +typedef struct NvmeIdNsDescr { + uint8_t nidt; + uint8_t nidl; + uint8_t rsvd2[2]; +} NvmeIdNsDescr; + +enum { + NVME_NIDT_EUI64_LEN = 8, + NVME_NIDT_NGUID_LEN = 16, + NVME_NIDT_UUID_LEN = 16, +}; + +enum NvmeNsIdentifierType { + NVME_NIDT_EUI64 = 0x1, + NVME_NIDT_NGUID = 0x2, + NVME_NIDT_UUID = 0x3, +}; /*Deallocate Logical Block Features*/ #define NVME_ID_NS_DLFEAT_GUARD_CRC(dlfeat) ((dlfeat) & 0x10) From patchwork Mon Jul 6 06:12:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278503 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B9F7C433DF for ; Mon, 6 Jul 2020 06:14:40 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 529BA20724 for ; Mon, 6 Jul 2020 06:14:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 529BA20724 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:60250 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKOl-0002vd-Jt for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:14:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60494) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNW-0000fu-Hk; Mon, 06 Jul 2020 02:13:23 -0400 Received: from charlie.dont.surf ([128.199.63.193]:57982) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNQ-0000uk-Jy; Mon, 06 Jul 2020 02:13:22 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id 9F4C6BF81F; Mon, 6 Jul 2020 06:13:12 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 03/18] hw/block/nvme: additional tracing Date: Mon, 6 Jul 2020 08:12:48 +0200 Message-Id: <20200706061303.246057-4-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add various additional tracing and streamline nvme_identify_ns and nvme_identify_nslist (they do not need to repeat the command, it is already in the trace name). Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 33 +++++++++++++++++++++++++++++++++ hw/block/trace-events | 13 +++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 766cd5b33bb1..09ef54d771c4 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -69,6 +69,20 @@ static void nvme_process_sq(void *opaque); +static uint16_t nvme_cid(NvmeRequest *req) +{ + if (!req) { + return 0xffff; + } + + return le16_to_cpu(req->cqe.cid); +} + +static uint16_t nvme_sqid(NvmeRequest *req) +{ + return le16_to_cpu(req->sq->sqid); +} + static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr) { hwaddr low = n->ctrl_mem.addr; @@ -331,6 +345,8 @@ static void nvme_post_cqes(void *opaque) static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req) { assert(cq->cqid == req->sq->cqid); + trace_pci_nvme_enqueue_req_completion(nvme_cid(req), cq->cqid, + req->status); QTAILQ_REMOVE(&req->sq->out_req_list, req, entry); QTAILQ_INSERT_TAIL(&cq->req_list, req, entry); timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500); @@ -343,6 +359,8 @@ static void nvme_rw_cb(void *opaque, int ret) NvmeCtrl *n = sq->ctrl; NvmeCQueue *cq = n->cq[sq->cqid]; + trace_pci_nvme_rw_cb(nvme_cid(req)); + if (!ret) { block_acct_done(blk_get_stats(n->conf.blk), &req->acct); req->status = NVME_SUCCESS; @@ -378,6 +396,8 @@ static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, uint64_t offset = slba << data_shift; uint32_t count = nlb << data_shift; + trace_pci_nvme_write_zeroes(nvme_cid(req), slba, nlb); + if (unlikely(slba + nlb > ns->id_ns.nsze)) { trace_pci_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze); return NVME_LBA_RANGE | NVME_DNR; @@ -445,6 +465,8 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) NvmeNamespace *ns; uint32_t nsid = le32_to_cpu(cmd->nsid); + trace_pci_nvme_io_cmd(nvme_cid(req), nsid, nvme_sqid(req), cmd->opcode); + if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces); return NVME_INVALID_NSID | NVME_DNR; @@ -876,6 +898,8 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { + trace_pci_nvme_admin_cmd(nvme_cid(req), nvme_sqid(req), cmd->opcode); + switch (cmd->opcode) { case NVME_ADM_CMD_DELETE_SQ: return nvme_del_sq(n, cmd); @@ -1204,6 +1228,8 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) uint8_t *ptr = (uint8_t *)&n->bar; uint64_t val = 0; + trace_pci_nvme_mmio_read(addr); + if (unlikely(addr & (sizeof(uint32_t) - 1))) { NVME_GUEST_ERR(pci_nvme_ub_mmiord_misaligned32, "MMIO read not 32-bit aligned," @@ -1273,6 +1299,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) return; } + trace_pci_nvme_mmio_doorbell_cq(cq->cqid, new_head); + start_sqs = nvme_cq_full(cq) ? 1 : 0; cq->head = new_head; if (start_sqs) { @@ -1311,6 +1339,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) return; } + trace_pci_nvme_mmio_doorbell_sq(sq->sqid, new_tail); + sq->tail = new_tail; timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500); } @@ -1320,6 +1350,9 @@ static void nvme_mmio_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { NvmeCtrl *n = (NvmeCtrl *)opaque; + + trace_pci_nvme_mmio_write(addr, data); + if (addr < sizeof(n->bar)) { nvme_write_bar(n, addr, data, size); } else if (addr >= 0x1000) { diff --git a/hw/block/trace-events b/hw/block/trace-events index 958fcc5508d1..c40c0d2e4b28 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -33,19 +33,28 @@ pci_nvme_irq_msix(uint32_t vector) "raising MSI-X IRQ vector %u" pci_nvme_irq_pin(void) "pulsing IRQ pin" pci_nvme_irq_masked(void) "IRQ is masked" pci_nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2=0x%"PRIx64"" +pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8"" +pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8"" pci_nvme_rw(const char *verb, uint32_t blk_count, uint64_t byte_count, uint64_t lba) "%s %"PRIu32" blocks (%"PRIu64" bytes) from LBA %"PRIu64"" +pci_nvme_rw_cb(uint16_t cid) "cid %"PRIu16"" +pci_nvme_write_zeroes(uint16_t cid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" slba %"PRIu64" nlb %"PRIu32"" pci_nvme_create_sq(uint64_t addr, uint16_t sqid, uint16_t cqid, uint16_t qsize, uint16_t qflags) "create submission queue, addr=0x%"PRIx64", sqid=%"PRIu16", cqid=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16"" pci_nvme_create_cq(uint64_t addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t qflags, int ien) "create completion queue, addr=0x%"PRIx64", cqid=%"PRIu16", vector=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16", ien=%d" pci_nvme_del_sq(uint16_t qid) "deleting submission queue sqid=%"PRIu16"" pci_nvme_del_cq(uint16_t cqid) "deleted completion queue, cqid=%"PRIu16"" pci_nvme_identify_ctrl(void) "identify controller" -pci_nvme_identify_ns(uint16_t ns) "identify namespace, nsid=%"PRIu16"" -pci_nvme_identify_nslist(uint16_t ns) "identify namespace list, nsid=%"PRIu16"" +pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32"" +pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32"" pci_nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s" pci_nvme_getfeat_numq(int result) "get feature number of queues, result=%d" pci_nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d" pci_nvme_setfeat_timestamp(uint64_t ts) "set feature timestamp = 0x%"PRIx64"" pci_nvme_getfeat_timestamp(uint64_t ts) "get feature timestamp = 0x%"PRIx64"" +pci_nvme_enqueue_req_completion(uint16_t cid, uint16_t cqid, uint16_t status) "cid %"PRIu16" cqid %"PRIu16" status 0x%"PRIx16"" +pci_nvme_mmio_read(uint64_t addr) "addr 0x%"PRIx64"" +pci_nvme_mmio_write(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" data 0x%"PRIx64"" +pci_nvme_mmio_doorbell_cq(uint16_t cqid, uint16_t new_head) "cqid %"PRIu16" new_head %"PRIu16"" +pci_nvme_mmio_doorbell_sq(uint16_t sqid, uint16_t new_tail) "cqid %"PRIu16" new_tail %"PRIu16"" pci_nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64"" pci_nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64"" pci_nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64"" From patchwork Mon Jul 6 06:12:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278504 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5C7C0C433E0 for ; Mon, 6 Jul 2020 06:14:34 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 334FB20724 for ; Mon, 6 Jul 2020 06:14:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 334FB20724 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59606 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKOf-0002fX-AJ for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:14:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60456) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNU-0000eL-Oe; Mon, 06 Jul 2020 02:13:20 -0400 Received: from charlie.dont.surf ([128.199.63.193]:57990) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNQ-0000ux-9e; Mon, 06 Jul 2020 02:13:20 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id 373DDBF83E; Mon, 6 Jul 2020 06:13:13 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 04/18] hw/block/nvme: add support for the abort command Date: Mon, 6 Jul 2020 08:12:49 +0200 Message-Id: <20200706061303.246057-5-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Required for compliance with NVMe revision 1.3d. See NVM Express 1.3d, Section 5.1 ("Abort command"). The Abort command is a best effort command; for now, the device always fails to abort the given command. Signed-off-by: Klaus Jensen Signed-off-by: Klaus Jensen Acked-by: Keith Busch Reviewed-by: Maxim Levitsky Reviewed-by: Dmitry Fomichev --- hw/block/nvme.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 09ef54d771c4..415d3b036897 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -775,6 +775,18 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd) } } +static uint16_t nvme_abort(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) +{ + uint16_t sqid = le32_to_cpu(cmd->cdw10) & 0xffff; + + req->cqe.result = 1; + if (nvme_check_sqid(n, sqid)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + return NVME_SUCCESS; +} + static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) { trace_pci_nvme_setfeat_timestamp(ts); @@ -911,6 +923,8 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) return nvme_create_cq(n, cmd); case NVME_ADM_CMD_IDENTIFY: return nvme_identify(n, cmd); + case NVME_ADM_CMD_ABORT: + return nvme_abort(n, cmd, req); case NVME_ADM_CMD_SET_FEATURES: return nvme_set_feature(n, cmd, req); case NVME_ADM_CMD_GET_FEATURES: @@ -1596,6 +1610,19 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->ieee[1] = 0x02; id->ieee[2] = 0xb3; id->oacs = cpu_to_le16(0); + + /* + * Because the controller always completes the Abort command immediately, + * there can never be more than one concurrently executing Abort command, + * so this value is never used for anything. Note that there can easily be + * many Abort commands in the queues, but they are not considered + * "executing" until processed by nvme_abort. + * + * The specification recommends a value of 3 for Abort Command Limit (four + * concurrently outstanding Abort commands), so lets use that though it is + * inconsequential. + */ + id->acl = 3; id->frmw = 7 << 1; id->lpa = 1 << 0; id->sqes = (0x6 << 4) | 0x6; From patchwork Mon Jul 6 06:12:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278502 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF7BFC433E1 for ; Mon, 6 Jul 2020 06:17:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8248320724 for ; Mon, 6 Jul 2020 06:17:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8248320724 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:41132 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKRE-0006wZ-KG for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:17:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60528) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNY-0000ig-Gy; Mon, 06 Jul 2020 02:13:24 -0400 Received: from charlie.dont.surf ([128.199.63.193]:58086) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNU-0000vi-OT; Mon, 06 Jul 2020 02:13:24 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id E1B5ABF849; Mon, 6 Jul 2020 06:13:13 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 05/18] hw/block/nvme: add temperature threshold feature Date: Mon, 6 Jul 2020 08:12:50 +0200 Message-Id: <20200706061303.246057-6-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen It might seem weird to implement this feature for an emulated device, but it is mandatory to support and the feature is useful for testing asynchronous event request support, which will be added in a later patch. Signed-off-by: Klaus Jensen Acked-by: Keith Busch Reviewed-by: Maxim Levitsky --- hw/block/nvme.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ hw/block/nvme.h | 1 + include/block/nvme.h | 5 ++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 415d3b036897..a330ccf91620 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -59,6 +59,9 @@ #define NVME_DB_SIZE 4 #define NVME_CMB_BIR 2 #define NVME_PMR_BIR 2 +#define NVME_TEMPERATURE 0x143 +#define NVME_TEMPERATURE_WARNING 0x157 +#define NVME_TEMPERATURE_CRITICAL 0x175 #define NVME_GUEST_ERR(trace, fmt, ...) \ do { \ @@ -841,9 +844,31 @@ static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { uint32_t dw10 = le32_to_cpu(cmd->cdw10); + uint32_t dw11 = le32_to_cpu(cmd->cdw11); uint32_t result; switch (dw10) { + case NVME_TEMPERATURE_THRESHOLD: + result = 0; + + /* + * The controller only implements the Composite Temperature sensor, so + * return 0 for all other sensors. + */ + if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { + break; + } + + switch (NVME_TEMP_THSEL(dw11)) { + case NVME_TEMP_THSEL_OVER: + result = n->features.temp_thresh_hi; + break; + case NVME_TEMP_THSEL_UNDER: + result = n->features.temp_thresh_low; + break; + } + + break; case NVME_VOLATILE_WRITE_CACHE: result = blk_enable_write_cache(n->conf.blk); trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); @@ -888,6 +913,23 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) uint32_t dw11 = le32_to_cpu(cmd->cdw11); switch (dw10) { + case NVME_TEMPERATURE_THRESHOLD: + if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { + break; + } + + switch (NVME_TEMP_THSEL(dw11)) { + case NVME_TEMP_THSEL_OVER: + n->features.temp_thresh_hi = NVME_TEMP_TMPTH(dw11); + break; + case NVME_TEMP_THSEL_UNDER: + n->features.temp_thresh_low = NVME_TEMP_TMPTH(dw11); + break; + default: + return NVME_INVALID_FIELD | NVME_DNR; + } + + break; case NVME_VOLATILE_WRITE_CACHE: blk_set_enable_write_cache(n->conf.blk, dw11 & 1); break; @@ -1468,6 +1510,7 @@ static void nvme_init_state(NvmeCtrl *n) n->namespaces = g_new0(NvmeNamespace, n->num_namespaces); n->sq = g_new0(NvmeSQueue *, n->params.max_ioqpairs + 1); n->cq = g_new0(NvmeCQueue *, n->params.max_ioqpairs + 1); + n->features.temp_thresh_hi = NVME_TEMPERATURE_WARNING; } static void nvme_init_blk(NvmeCtrl *n, Error **errp) @@ -1625,6 +1668,11 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->acl = 3; id->frmw = 7 << 1; id->lpa = 1 << 0; + + /* recommended default value (~70 C) */ + id->wctemp = cpu_to_le16(NVME_TEMPERATURE_WARNING); + id->cctemp = cpu_to_le16(NVME_TEMPERATURE_CRITICAL); + id->sqes = (0x6 << 4) | 0x6; id->cqes = (0x4 << 4) | 0x4; id->nn = cpu_to_le32(n->num_namespaces); diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 1d30c0bca283..e3a2c907e210 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -107,6 +107,7 @@ typedef struct NvmeCtrl { NvmeSQueue admin_sq; NvmeCQueue admin_cq; NvmeIdCtrl id_ctrl; + NvmeFeatureVal features; } NvmeCtrl; /* calculate the number of LBAs that the namespace can accomodate */ diff --git a/include/block/nvme.h b/include/block/nvme.h index 2a80d2a7ed89..d2c457695b38 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -860,7 +860,10 @@ enum NvmeIdCtrlOncs { typedef struct NvmeFeatureVal { uint32_t arbitration; uint32_t power_mgmt; - uint32_t temp_thresh; + struct { + uint16_t temp_thresh_hi; + uint16_t temp_thresh_low; + }; uint32_t err_rec; uint32_t volatile_wc; uint32_t num_queues; From patchwork Mon Jul 6 06:12:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278500 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4EE99C433E0 for ; Mon, 6 Jul 2020 06:18:48 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 20FDD20708 for ; Mon, 6 Jul 2020 06:18:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 20FDD20708 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49388 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKSl-0001t3-Di for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:18:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60760) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNt-0001hw-R7; Mon, 06 Jul 2020 02:13:45 -0400 Received: from charlie.dont.surf ([128.199.63.193]:58132) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNr-0000wf-OQ; Mon, 06 Jul 2020 02:13:45 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id C7EA4BF858; Mon, 6 Jul 2020 06:13:16 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 11/18] hw/block/nvme: add remaining mandatory controller parameters Date: Mon, 6 Jul 2020 08:12:56 +0200 Message-Id: <20200706061303.246057-12-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add support for any remaining mandatory controller operating parameters (features). Signed-off-by: Klaus Jensen Reviewed-by: Dmitry Fomichev --- hw/block/nvme.c | 56 ++++++++++++++++++++++++++++++++++++++----- hw/block/trace-events | 2 ++ include/block/nvme.h | 10 +++++++- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 8fce2ebf69e7..2d85e853403f 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -71,6 +71,20 @@ " in %s: " fmt "\n", __func__, ## __VA_ARGS__); \ } while (0) +static const bool nvme_feature_support[NVME_FID_MAX] = { + [NVME_ARBITRATION] = true, + [NVME_POWER_MANAGEMENT] = true, + [NVME_TEMPERATURE_THRESHOLD] = true, + [NVME_ERROR_RECOVERY] = true, + [NVME_VOLATILE_WRITE_CACHE] = true, + [NVME_NUMBER_OF_QUEUES] = true, + [NVME_INTERRUPT_COALESCING] = true, + [NVME_INTERRUPT_VECTOR_CONF] = true, + [NVME_WRITE_ATOMICITY] = true, + [NVME_ASYNCHRONOUS_EVENT_CONF] = true, + [NVME_TIMESTAMP] = true, +}; + static void nvme_process_sq(void *opaque); static uint16_t nvme_cid(NvmeRequest *req) @@ -1070,8 +1084,20 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint32_t dw11 = le32_to_cpu(cmd->cdw11); uint32_t result; + uint8_t fid = NVME_GETSETFEAT_FID(dw10); + uint16_t iv; - switch (dw10) { + static const uint32_t nvme_feature_default[NVME_FID_MAX] = { + [NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT, + }; + + trace_pci_nvme_getfeat(nvme_cid(req), fid, dw11); + + if (!nvme_feature_support[fid]) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + switch (fid) { case NVME_TEMPERATURE_THRESHOLD: result = 0; @@ -1101,6 +1127,18 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) result = (n->params.max_ioqpairs - 1) | ((n->params.max_ioqpairs - 1) << 16); trace_pci_nvme_getfeat_numq(result); + break; + case NVME_INTERRUPT_VECTOR_CONF: + iv = dw11 & 0xffff; + if (iv >= n->params.max_ioqpairs + 1) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + result = iv; + if (iv == n->admin_cq.vector) { + result |= NVME_INTVC_NOCOALESCING; + } + break; case NVME_ASYNCHRONOUS_EVENT_CONF: result = n->features.async_config; @@ -1108,8 +1146,8 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) case NVME_TIMESTAMP: return nvme_get_feature_timestamp(n, cmd); default: - trace_pci_nvme_err_invalid_getfeat(dw10); - return NVME_INVALID_FIELD | NVME_DNR; + result = nvme_feature_default[fid]; + break; } req->cqe.result = cpu_to_le32(result); @@ -1138,8 +1176,15 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint32_t dw11 = le32_to_cpu(cmd->cdw11); + uint8_t fid = NVME_GETSETFEAT_FID(dw10); - switch (dw10) { + trace_pci_nvme_setfeat(nvme_cid(req), fid, dw11); + + if (!nvme_feature_support[fid]) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + switch (fid) { case NVME_TEMPERATURE_THRESHOLD: if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { break; @@ -1186,8 +1231,7 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) case NVME_TIMESTAMP: return nvme_set_feature_timestamp(n, cmd); default: - trace_pci_nvme_err_invalid_setfeat(dw10); - return NVME_INVALID_FIELD | NVME_DNR; + return NVME_FEAT_NOT_CHANGEABLE | NVME_DNR; } return NVME_SUCCESS; } diff --git a/hw/block/trace-events b/hw/block/trace-events index 091af16ca7d7..42e62f4649f8 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -46,6 +46,8 @@ pci_nvme_identify_ctrl(void) "identify controller" pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32"" pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32"" pci_nvme_get_log(uint16_t cid, uint8_t lid, uint8_t lsp, uint8_t rae, uint32_t len, uint64_t off) "cid %"PRIu16" lid 0x%"PRIx8" lsp 0x%"PRIx8" rae 0x%"PRIx8" len %"PRIu32" off %"PRIu64"" +pci_nvme_getfeat(uint16_t cid, uint8_t fid, uint32_t cdw11) "cid %"PRIu16" fid 0x%"PRIx8" cdw11 0x%"PRIx32"" +pci_nvme_setfeat(uint16_t cid, uint8_t fid, uint32_t cdw11) "cid %"PRIu16" fid 0x%"PRIx8" cdw11 0x%"PRIx32"" pci_nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s" pci_nvme_getfeat_numq(int result) "get feature number of queues, result=%d" pci_nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d" diff --git a/include/block/nvme.h b/include/block/nvme.h index 0dce15af6bcf..cd396111b2f5 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -662,6 +662,7 @@ enum NvmeStatusCodes { NVME_FW_REQ_RESET = 0x010b, NVME_INVALID_QUEUE_DEL = 0x010c, NVME_FID_NOT_SAVEABLE = 0x010d, + NVME_FEAT_NOT_CHANGEABLE = 0x010e, NVME_FID_NOT_NSID_SPEC = 0x010f, NVME_FW_REQ_SUSYSTEM_RESET = 0x0110, NVME_CONFLICTING_ATTRS = 0x0180, @@ -866,6 +867,7 @@ enum NvmeIdCtrlLpa { #define NVME_CTRL_SGLS_ADDR_OFFSET (0x1 << 20) #define NVME_ARB_AB(arb) (arb & 0x7) +#define NVME_ARB_AB_NOLIMIT 0x7 #define NVME_ARB_LPW(arb) ((arb >> 8) & 0xff) #define NVME_ARB_MPW(arb) ((arb >> 16) & 0xff) #define NVME_ARB_HPW(arb) ((arb >> 24) & 0xff) @@ -873,6 +875,8 @@ enum NvmeIdCtrlLpa { #define NVME_INTC_THR(intc) (intc & 0xff) #define NVME_INTC_TIME(intc) ((intc >> 8) & 0xff) +#define NVME_INTVC_NOCOALESCING (0x1 << 16) + #define NVME_TEMP_THSEL(temp) ((temp >> 20) & 0x3) #define NVME_TEMP_THSEL_OVER 0x0 #define NVME_TEMP_THSEL_UNDER 0x1 @@ -899,9 +903,13 @@ enum NvmeFeatureIds { NVME_WRITE_ATOMICITY = 0xa, NVME_ASYNCHRONOUS_EVENT_CONF = 0xb, NVME_TIMESTAMP = 0xe, - NVME_SOFTWARE_PROGRESS_MARKER = 0x80 + NVME_SOFTWARE_PROGRESS_MARKER = 0x80, + NVME_FID_MAX = 0x100, }; +#define NVME_GETSETFEAT_FID_MASK 0xff +#define NVME_GETSETFEAT_FID(dw10) (dw10 & NVME_GETSETFEAT_FID_MASK) + typedef struct NvmeRangeType { uint8_t type; uint8_t attributes; From patchwork Mon Jul 6 06:12:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278501 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF2F5C433E0 for ; Mon, 6 Jul 2020 06:17:27 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8606120708 for ; Mon, 6 Jul 2020 06:17:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8606120708 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:42534 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKRS-0007aM-NP for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:17:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60836) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNw-0001ot-9F; Mon, 06 Jul 2020 02:13:48 -0400 Received: from charlie.dont.surf ([128.199.63.193]:58134) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNr-0000wi-Tq; Mon, 06 Jul 2020 02:13:47 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id 3C2B4BF85A; Mon, 6 Jul 2020 06:13:17 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 12/18] hw/block/nvme: support the get/set features select and save fields Date: Mon, 6 Jul 2020 08:12:57 +0200 Message-Id: <20200706061303.246057-13-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Since the device does not have any persistent state storage, no features are "saveable" and setting the Save (SV) field in any Set Features command will result in a Feature Identifier Not Saveable status code. Similarly, if the Select (SEL) field is set to request saved values, the devices will (as it should) return the default values instead. Since this also introduces "Supported Capabilities", the nsid field is now also checked for validity wrt. the feature being get/set'ed. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 103 +++++++++++++++++++++++++++++++++++++----- hw/block/trace-events | 4 +- include/block/nvme.h | 27 ++++++++++- 3 files changed, 119 insertions(+), 15 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 2d85e853403f..df8b786e4875 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -85,6 +85,14 @@ static const bool nvme_feature_support[NVME_FID_MAX] = { [NVME_TIMESTAMP] = true, }; +static const uint32_t nvme_feature_cap[NVME_FID_MAX] = { + [NVME_TEMPERATURE_THRESHOLD] = NVME_FEAT_CAP_CHANGE, + [NVME_VOLATILE_WRITE_CACHE] = NVME_FEAT_CAP_CHANGE, + [NVME_NUMBER_OF_QUEUES] = NVME_FEAT_CAP_CHANGE, + [NVME_ASYNCHRONOUS_EVENT_CONF] = NVME_FEAT_CAP_CHANGE, + [NVME_TIMESTAMP] = NVME_FEAT_CAP_CHANGE, +}; + static void nvme_process_sq(void *opaque); static uint16_t nvme_cid(NvmeRequest *req) @@ -1083,20 +1091,47 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint32_t dw11 = le32_to_cpu(cmd->cdw11); + uint32_t nsid = le32_to_cpu(cmd->nsid); uint32_t result; uint8_t fid = NVME_GETSETFEAT_FID(dw10); + NvmeGetFeatureSelect sel = NVME_GETFEAT_SELECT(dw10); uint16_t iv; static const uint32_t nvme_feature_default[NVME_FID_MAX] = { [NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT, }; - trace_pci_nvme_getfeat(nvme_cid(req), fid, dw11); + trace_pci_nvme_getfeat(nvme_cid(req), fid, sel, dw11); if (!nvme_feature_support[fid]) { return NVME_INVALID_FIELD | NVME_DNR; } + if (nvme_feature_cap[fid] & NVME_FEAT_CAP_NS) { + if (!nsid || nsid > n->num_namespaces) { + /* + * The Reservation Notification Mask and Reservation Persistence + * features require a status code of Invalid Field in Command when + * NSID is 0xFFFFFFFF. Since the device does not support those + * features we can always return Invalid Namespace or Format as we + * should do for all other features. + */ + return NVME_INVALID_NSID | NVME_DNR; + } + } + + switch (sel) { + case NVME_GETFEAT_SELECT_CURRENT: + break; + case NVME_GETFEAT_SELECT_SAVED: + /* no features are saveable by the controller; fallthrough */ + case NVME_GETFEAT_SELECT_DEFAULT: + goto defaults; + case NVME_GETFEAT_SELECT_CAP: + result = nvme_feature_cap[fid]; + goto out; + } + switch (fid) { case NVME_TEMPERATURE_THRESHOLD: result = 0; @@ -1106,22 +1141,45 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) * return 0 for all other sensors. */ if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { - break; + goto out; } switch (NVME_TEMP_THSEL(dw11)) { case NVME_TEMP_THSEL_OVER: result = n->features.temp_thresh_hi; - break; + goto out; case NVME_TEMP_THSEL_UNDER: result = n->features.temp_thresh_low; - break; + goto out; } - break; + return NVME_INVALID_FIELD | NVME_DNR; case NVME_VOLATILE_WRITE_CACHE: result = blk_enable_write_cache(n->conf.blk); trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); + goto out; + case NVME_ASYNCHRONOUS_EVENT_CONF: + result = n->features.async_config; + goto out; + case NVME_TIMESTAMP: + return nvme_get_feature_timestamp(n, cmd); + default: + break; + } + +defaults: + switch (fid) { + case NVME_TEMPERATURE_THRESHOLD: + result = 0; + + if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { + break; + } + + if (NVME_TEMP_THSEL(dw11) == NVME_TEMP_THSEL_OVER) { + result = NVME_TEMPERATURE_WARNING; + } + break; case NVME_NUMBER_OF_QUEUES: result = (n->params.max_ioqpairs - 1) | @@ -1140,16 +1198,12 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) } break; - case NVME_ASYNCHRONOUS_EVENT_CONF: - result = n->features.async_config; - break; - case NVME_TIMESTAMP: - return nvme_get_feature_timestamp(n, cmd); default: result = nvme_feature_default[fid]; break; } +out: req->cqe.result = cpu_to_le32(result); return NVME_SUCCESS; } @@ -1176,14 +1230,37 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint32_t dw11 = le32_to_cpu(cmd->cdw11); + uint32_t nsid = le32_to_cpu(cmd->nsid); uint8_t fid = NVME_GETSETFEAT_FID(dw10); + uint8_t save = NVME_SETFEAT_SAVE(dw10); - trace_pci_nvme_setfeat(nvme_cid(req), fid, dw11); + trace_pci_nvme_setfeat(nvme_cid(req), fid, save, dw11); + + if (save) { + return NVME_FID_NOT_SAVEABLE | NVME_DNR; + } if (!nvme_feature_support[fid]) { return NVME_INVALID_FIELD | NVME_DNR; } + if (nvme_feature_cap[fid] & NVME_FEAT_CAP_NS) { + if (!nsid || (nsid != NVME_NSID_BROADCAST && + nsid > n->num_namespaces)) { + return NVME_INVALID_NSID | NVME_DNR; + } + } else if (nsid && nsid != NVME_NSID_BROADCAST) { + if (nsid > n->num_namespaces) { + return NVME_INVALID_NSID | NVME_DNR; + } + + return NVME_FEAT_NOT_NS_SPEC | NVME_DNR; + } + + if (!(nvme_feature_cap[fid] & NVME_FEAT_CAP_CHANGE)) { + return NVME_FEAT_NOT_CHANGEABLE | NVME_DNR; + } + switch (fid) { case NVME_TEMPERATURE_THRESHOLD: if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { @@ -2028,7 +2105,9 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->sqes = (0x6 << 4) | 0x6; id->cqes = (0x4 << 4) | 0x4; id->nn = cpu_to_le32(n->num_namespaces); - id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS | NVME_ONCS_TIMESTAMP); + id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS | NVME_ONCS_TIMESTAMP | + NVME_ONCS_FEATURES); + id->psd[0].mp = cpu_to_le16(0x9c4); id->psd[0].enlat = cpu_to_le32(0x10); id->psd[0].exlat = cpu_to_le32(0x4); diff --git a/hw/block/trace-events b/hw/block/trace-events index 42e62f4649f8..4a4ef34071df 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -46,8 +46,8 @@ pci_nvme_identify_ctrl(void) "identify controller" pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32"" pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32"" pci_nvme_get_log(uint16_t cid, uint8_t lid, uint8_t lsp, uint8_t rae, uint32_t len, uint64_t off) "cid %"PRIu16" lid 0x%"PRIx8" lsp 0x%"PRIx8" rae 0x%"PRIx8" len %"PRIu32" off %"PRIu64"" -pci_nvme_getfeat(uint16_t cid, uint8_t fid, uint32_t cdw11) "cid %"PRIu16" fid 0x%"PRIx8" cdw11 0x%"PRIx32"" -pci_nvme_setfeat(uint16_t cid, uint8_t fid, uint32_t cdw11) "cid %"PRIu16" fid 0x%"PRIx8" cdw11 0x%"PRIx32"" +pci_nvme_getfeat(uint16_t cid, uint8_t fid, uint8_t sel, uint32_t cdw11) "cid %"PRIu16" fid 0x%"PRIx8" sel 0x%"PRIx8" cdw11 0x%"PRIx32"" +pci_nvme_setfeat(uint16_t cid, uint8_t fid, uint8_t save, uint32_t cdw11) "cid %"PRIu16" fid 0x%"PRIx8" save 0x%"PRIx8" cdw11 0x%"PRIx32"" pci_nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s" pci_nvme_getfeat_numq(int result) "get feature number of queues, result=%d" pci_nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d" diff --git a/include/block/nvme.h b/include/block/nvme.h index cd396111b2f5..179e20a01477 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -663,7 +663,7 @@ enum NvmeStatusCodes { NVME_INVALID_QUEUE_DEL = 0x010c, NVME_FID_NOT_SAVEABLE = 0x010d, NVME_FEAT_NOT_CHANGEABLE = 0x010e, - NVME_FID_NOT_NSID_SPEC = 0x010f, + NVME_FEAT_NOT_NS_SPEC = 0x010f, NVME_FW_REQ_SUSYSTEM_RESET = 0x0110, NVME_CONFLICTING_ATTRS = 0x0180, NVME_INVALID_PROT_INFO = 0x0181, @@ -907,9 +907,32 @@ enum NvmeFeatureIds { NVME_FID_MAX = 0x100, }; +typedef enum NvmeFeatureCap { + NVME_FEAT_CAP_SAVE = 1 << 0, + NVME_FEAT_CAP_NS = 1 << 1, + NVME_FEAT_CAP_CHANGE = 1 << 2, +} NvmeFeatureCap; + +typedef enum NvmeGetFeatureSelect { + NVME_GETFEAT_SELECT_CURRENT = 0x0, + NVME_GETFEAT_SELECT_DEFAULT = 0x1, + NVME_GETFEAT_SELECT_SAVED = 0x2, + NVME_GETFEAT_SELECT_CAP = 0x3, +} NvmeGetFeatureSelect; + #define NVME_GETSETFEAT_FID_MASK 0xff #define NVME_GETSETFEAT_FID(dw10) (dw10 & NVME_GETSETFEAT_FID_MASK) +#define NVME_GETFEAT_SELECT_SHIFT 8 +#define NVME_GETFEAT_SELECT_MASK 0x7 +#define NVME_GETFEAT_SELECT(dw10) \ + ((dw10 >> NVME_GETFEAT_SELECT_SHIFT) & NVME_GETFEAT_SELECT_MASK) + +#define NVME_SETFEAT_SAVE_SHIFT 31 +#define NVME_SETFEAT_SAVE_MASK 0x1 +#define NVME_SETFEAT_SAVE(dw10) \ + ((dw10 >> NVME_SETFEAT_SAVE_SHIFT) & NVME_SETFEAT_SAVE_MASK) + typedef struct NvmeRangeType { uint8_t type; uint8_t attributes; @@ -926,6 +949,8 @@ typedef struct NvmeLBAF { uint8_t rp; } NvmeLBAF; +#define NVME_NSID_BROADCAST 0xffffffff + typedef struct NvmeIdNs { uint64_t nsze; uint64_t ncap; From patchwork Mon Jul 6 06:12:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278496 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94C40C433E0 for ; Mon, 6 Jul 2020 06:24:09 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 68C422075B for ; Mon, 6 Jul 2020 06:24:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 68C422075B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40464 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKXw-000226-Ga for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:24:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60804) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNv-0001lY-5k; Mon, 06 Jul 2020 02:13:47 -0400 Received: from charlie.dont.surf ([128.199.63.193]:58138) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNt-0000x0-Da; Mon, 06 Jul 2020 02:13:46 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id A4AB0BF862; Mon, 6 Jul 2020 06:13:17 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 13/18] hw/block/nvme: make sure ncqr and nsqr is valid Date: Mon, 6 Jul 2020 08:12:58 +0200 Message-Id: <20200706061303.246057-14-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen 0xffff is not an allowed value for NCQR and NSQR in Set Features on Number of Queues. Signed-off-by: Klaus Jensen Acked-by: Keith Busch Reviewed-by: Maxim Levitsky Reviewed-by: Dmitry Fomichev --- hw/block/nvme.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index df8b786e4875..37e4fd8dfce1 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -1295,6 +1295,14 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) blk_set_enable_write_cache(n->conf.blk, dw11 & 1); break; case NVME_NUMBER_OF_QUEUES: + /* + * NVMe v1.3, Section 5.21.1.7: 0xffff is not an allowed value for NCQR + * and NSQR. + */ + if ((dw11 & 0xffff) == 0xffff || ((dw11 >> 16) & 0xffff) == 0xffff) { + return NVME_INVALID_FIELD | NVME_DNR; + } + trace_pci_nvme_setfeat_numq((dw11 & 0xFFFF) + 1, ((dw11 >> 16) & 0xFFFF) + 1, n->params.max_ioqpairs, From patchwork Mon Jul 6 06:13:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278497 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5E7ADC433E1 for ; Mon, 6 Jul 2020 06:22:07 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 371752075B for ; Mon, 6 Jul 2020 06:22:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 371752075B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:34660 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKVy-0007h7-Ga for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:22:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60844) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNx-0001t9-Jz; Mon, 06 Jul 2020 02:13:49 -0400 Received: from charlie.dont.surf ([128.199.63.193]:58140) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNt-0000xB-OP; Mon, 06 Jul 2020 02:13:49 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id 9982EBF86A; Mon, 6 Jul 2020 06:13:18 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 15/18] hw/block/nvme: reject invalid nsid values in active namespace id list Date: Mon, 6 Jul 2020 08:13:00 +0200 Message-Id: <20200706061303.246057-16-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Reject the nsid broadcast value (0xffffffff) and 0xfffffffe in the Active Namespace ID list. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index fc58f3d76530..af39126cd8d1 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -992,6 +992,16 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c) trace_pci_nvme_identify_nslist(min_nsid); + /* + * Both 0xffffffff (NVME_NSID_BROADCAST) and 0xfffffffe are invalid values + * since the Active Namespace ID List should return namespaces with ids + * *higher* than the NSID specified in the command. This is also specified + * in the spec (NVM Express v1.3d, Section 5.15.4). + */ + if (min_nsid >= NVME_NSID_BROADCAST - 1) { + return NVME_INVALID_NSID | NVME_DNR; + } + list = g_malloc0(data_len); for (i = 0; i < n->num_namespaces; i++) { if (i < min_nsid) { From patchwork Mon Jul 6 06:13:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 278498 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C94BC433DF for ; Mon, 6 Jul 2020 06:20:35 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2207B20739 for ; Mon, 6 Jul 2020 06:20:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2207B20739 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=irrelevant.dk Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:57118 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsKUU-0005OM-Bt for qemu-devel@archiver.kernel.org; Mon, 06 Jul 2020 02:20:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60842) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNx-0001sI-DY; Mon, 06 Jul 2020 02:13:49 -0400 Received: from charlie.dont.surf ([128.199.63.193]:58142) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jsKNt-0000xD-Pb; Mon, 06 Jul 2020 02:13:49 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by charlie.dont.surf (Postfix) with ESMTPSA id 0CCD0BF5FF; Mon, 6 Jul 2020 06:13:19 +0000 (UTC) From: Klaus Jensen To: qemu-block@nongnu.org Subject: [PATCH v3 16/18] hw/block/nvme: enforce valid queue creation sequence Date: Mon, 6 Jul 2020 08:13:01 +0200 Message-Id: <20200706061303.246057-17-its@irrelevant.dk> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200706061303.246057-1-its@irrelevant.dk> References: <20200706061303.246057-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=128.199.63.193; envelope-from=its@irrelevant.dk; helo=charlie.dont.surf X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 02:13:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Dmitry Fomichev , Klaus Jensen , qemu-devel@nongnu.org, Max Reitz , Klaus Jensen , Keith Busch , Javier Gonzalez , Maxim Levitsky , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?b?w6k=?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Support returning Command Sequence Error if Set Features on Number of Queues is called after queues have been created. Signed-off-by: Klaus Jensen Reviewed-by: Maxim Levitsky Reviewed-by: Dmitry Fomichev --- hw/block/nvme.c | 12 ++++++++++++ hw/block/nvme.h | 1 + 2 files changed, 13 insertions(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index af39126cd8d1..07d58aa945f2 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -946,6 +946,13 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd) cq = g_malloc0(sizeof(*cq)); nvme_init_cq(cq, n, prp1, cqid, vector, qsize + 1, NVME_CQ_FLAGS_IEN(qflags)); + + /* + * It is only required to set qs_created when creating a completion queue; + * creating a submission queue without a matching completion queue will + * fail. + */ + n->qs_created = true; return NVME_SUCCESS; } @@ -1346,6 +1353,10 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) blk_set_enable_write_cache(n->conf.blk, dw11 & 1); break; case NVME_NUMBER_OF_QUEUES: + if (n->qs_created) { + return NVME_CMD_SEQ_ERROR | NVME_DNR; + } + /* * NVMe v1.3, Section 5.21.1.7: 0xffff is not an allowed value for NCQR * and NSQR. @@ -1478,6 +1489,7 @@ static void nvme_clear_ctrl(NvmeCtrl *n) n->aer_queued = 0; n->outstanding_aers = 0; + n->qs_created = false; blk_flush(n->conf.blk); n->bar.cc = 0; diff --git a/hw/block/nvme.h b/hw/block/nvme.h index b93067c9e4a1..0b6a8ae66559 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -95,6 +95,7 @@ typedef struct NvmeCtrl { BlockConf conf; NvmeParams params; + bool qs_created; uint32_t page_size; uint16_t page_bits; uint16_t max_prp_ents;