From patchwork Fri Sep 4 14:19:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274501 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,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 A5CC3C2D0A7 for ; Fri, 4 Sep 2020 14:21:39 +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 5C405206B7 for ; Fri, 4 Sep 2020 14:21:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="aK/EdPfM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5C405206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:58738 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECaw-0004E3-Go for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:21:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60816) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZy-0002Q5-Uw; Fri, 04 Sep 2020 10:20:38 -0400 Received: from charlie.dont.surf ([128.199.63.193]:47858) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZv-0002gY-67; Fri, 04 Sep 2020 10:20:38 -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 33033BF86A; Fri, 4 Sep 2020 14:20:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229231; bh=hwu6doMnOXapU+iu6OF0pVkM5orkUgvHjDUFvp/qW1w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aK/EdPfMbjjAaQFHLBq1dzziiXekAlH6yNQ5L0KLNQkmp0IelGphA6+AIHjcI9/3h JKYwGSNls5om4cmcQaS8Cma4DMsxrTeq9n6xBHrCXIxI1vwXbMqIFOPhcFNQpo2ATC sAAVkQzWZsA2npV0jCMDG5Fqo120IOUWjUB3kzA7XqMemeViw4wet78Tdwgbq/ezqK 1IqEOhexn6LUBjeuVYNa6UH6sne1HqASp2n6hA41oa/MAuHgTus/SleokoCg+YY4+X H8h+ZnfCrOjUhEXQpCeT/+jLP2mXn0yDGOrYV28jBVFYAuOgJdYCpFi6l2oIC3Gi6T 20fZ9aBVGgBow== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 01/17] pci: pass along the return value of dma_memory_rw Date: Fri, 4 Sep 2020 16:19:40 +0200 Message-Id: <20200904141956.576630-2-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Some devices might want to know the return value of dma_memory_rw, so pass it along instead of ignoring it. There are no existing users of the return value, so this patch should be safe. Signed-off-by: Klaus Jensen Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Acked-by: Keith Busch --- include/hw/pci/pci.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 4ca7258b5b71..896cef9ad476 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -788,8 +788,7 @@ static inline AddressSpace *pci_get_address_space(PCIDevice *dev) static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir) { - dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); - return 0; + return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); } static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, From patchwork Fri Sep 4 14:19:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274499 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 A5FA0C433E2 for ; Fri, 4 Sep 2020 14:23:24 +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 538512074D for ; Fri, 4 Sep 2020 14:23:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="cFn43aX0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 538512074D Authentication-Results: mail.kernel.org; dmarc=fail (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]:40174 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECcd-0008BB-8Y for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:23:23 -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 1kECZz-0002QQ-MV; Fri, 04 Sep 2020 10:20:39 -0400 Received: from charlie.dont.surf ([128.199.63.193]:47874) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZv-0002gp-BJ; Fri, 04 Sep 2020 10:20:39 -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 AC157BF8E7; Fri, 4 Sep 2020 14:20:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229232; bh=+LVYT8u/sgy2SdJk+2GYEVmsu8mUtbPV7TqY7WEojSE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cFn43aX0QajOqyc6ZcSnPk348A+mO4vVO0Fw6Q0NlCnH+t9cueD9c6NRqnkojhx/a xWJLJIZ1bfk0pKVQlgk5O9wfE4mXvqyeBnzoBIEcc380udGe7qB2EbR+FBV8p0uScG Ir1LBjJeNDU5xp7SVshtsP9bXXNlTFnjPimRXIGfVLlU43J5UOnlodKgvSKwn+baKx rfSRvs3NKBykJWU9c5Y9zeYBWcqH32EH4ikBuqlWSxmbQczWT/U9jF11/Hj4pElZfO E2pwZKMAqKZ2JGAKltCtkW2HVytQ4+/6dVpnhNZCi6aXfZQqkFsOCL4gOaqyhfmud3 Oe7ahbX/MARMA== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 02/17] hw/block/nvme: handle dma errors Date: Fri, 4 Sep 2020 16:19:41 +0200 Message-Id: <20200904141956.576630-3-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen , Maxim Levitsky Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Handling DMA errors gracefully is required for the device to pass the block/011 test ("disable PCI device while doing I/O") in the blktests suite. With this patch the device passes the test by retrying "critical" transfers (posting of completion entries and processing of submission queue entries). If DMA errors occur at any other point in the execution of the command (say, while mapping the PRPs), the command is aborted with a Data Transfer Error status code. Signed-off-by: Klaus Jensen Acked-by: Keith Busch Reviewed-by: Maxim Levitsky --- hw/block/nvme.c | 43 ++++++++++++++++++++++++++++++++----------- hw/block/trace-events | 2 ++ include/block/nvme.h | 2 +- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 63078f600920..49bcdf31ced6 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -140,14 +140,14 @@ static inline void *nvme_addr_to_cmb(NvmeCtrl *n, hwaddr addr) return &n->cmbuf[addr - n->ctrl_mem.addr]; } -static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) +static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) { if (n->bar.cmbsz && nvme_addr_is_cmb(n, addr)) { memcpy(buf, nvme_addr_to_cmb(n, addr), size); - return; + return 0; } - pci_dma_read(&n->parent_obj, addr, buf, size); + return pci_dma_read(&n->parent_obj, addr, buf, size); } static int nvme_check_sqid(NvmeCtrl *n, uint16_t sqid) @@ -253,7 +253,7 @@ static uint16_t nvme_map_addr_cmb(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr, trace_pci_nvme_map_addr_cmb(addr, len); if (!nvme_addr_is_cmb(n, addr) || !nvme_addr_is_cmb(n, addr + len - 1)) { - return NVME_DATA_TRAS_ERROR; + return NVME_DATA_TRANSFER_ERROR; } qemu_iovec_add(iov, nvme_addr_to_cmb(n, addr), len); @@ -307,6 +307,7 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2, int num_prps = (len >> n->page_bits) + 1; uint16_t status; bool prp_list_in_cmb = false; + int ret; QEMUSGList *qsg = &req->qsg; QEMUIOVector *iov = &req->iov; @@ -347,7 +348,11 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2, nents = (len + n->page_size - 1) >> n->page_bits; prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t); - nvme_addr_read(n, prp2, (void *)prp_list, prp_trans); + ret = nvme_addr_read(n, prp2, (void *)prp_list, prp_trans); + if (ret) { + trace_pci_nvme_err_addr_read(prp2); + return NVME_DATA_TRANSFER_ERROR; + } while (len != 0) { uint64_t prp_ent = le64_to_cpu(prp_list[i]); @@ -364,8 +369,12 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2, i = 0; nents = (len + n->page_size - 1) >> n->page_bits; prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t); - nvme_addr_read(n, prp_ent, (void *)prp_list, - prp_trans); + ret = nvme_addr_read(n, prp_ent, (void *)prp_list, + prp_trans); + if (ret) { + trace_pci_nvme_err_addr_read(prp_ent); + return NVME_DATA_TRANSFER_ERROR; + } prp_ent = le64_to_cpu(prp_list[i]); } @@ -457,6 +466,7 @@ static void nvme_post_cqes(void *opaque) NvmeCQueue *cq = opaque; NvmeCtrl *n = cq->ctrl; NvmeRequest *req, *next; + int ret; QTAILQ_FOREACH_SAFE(req, &cq->req_list, entry, next) { NvmeSQueue *sq; @@ -466,15 +476,21 @@ static void nvme_post_cqes(void *opaque) break; } - QTAILQ_REMOVE(&cq->req_list, req, entry); sq = req->sq; req->cqe.status = cpu_to_le16((req->status << 1) | cq->phase); req->cqe.sq_id = cpu_to_le16(sq->sqid); req->cqe.sq_head = cpu_to_le16(sq->head); addr = cq->dma_addr + cq->tail * n->cqe_size; + ret = pci_dma_write(&n->parent_obj, addr, (void *)&req->cqe, + sizeof(req->cqe)); + if (ret) { + trace_pci_nvme_err_addr_write(addr); + timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + 500 * SCALE_MS); + break; + } + QTAILQ_REMOVE(&cq->req_list, req, entry); nvme_inc_cq_tail(cq); - pci_dma_write(&n->parent_obj, addr, (void *)&req->cqe, - sizeof(req->cqe)); nvme_req_exit(req); QTAILQ_INSERT_TAIL(&sq->req_list, req, entry); } @@ -1611,7 +1627,12 @@ static void nvme_process_sq(void *opaque) while (!(nvme_sq_empty(sq) || QTAILQ_EMPTY(&sq->req_list))) { addr = sq->dma_addr + sq->head * n->sqe_size; - nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd)); + if (nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd))) { + trace_pci_nvme_err_addr_read(addr); + timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + 500 * SCALE_MS); + break; + } nvme_inc_sq_head(sq); req = QTAILQ_FIRST(&sq->req_list); diff --git a/hw/block/trace-events b/hw/block/trace-events index 72cf2d15cb8e..50d5702e6b80 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -86,6 +86,8 @@ pci_nvme_mmio_shutdown_cleared(void) "shutdown bit cleared" # nvme traces for error conditions pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu" +pci_nvme_err_addr_read(uint64_t addr) "addr 0x%"PRIx64"" +pci_nvme_err_addr_write(uint64_t addr) "addr 0x%"PRIx64"" pci_nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size" pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or not page aligned: 0x%"PRIx64"" pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64"" diff --git a/include/block/nvme.h b/include/block/nvme.h index 65e68a82c897..c8d0a3473f0d 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -630,7 +630,7 @@ enum NvmeStatusCodes { NVME_INVALID_OPCODE = 0x0001, NVME_INVALID_FIELD = 0x0002, NVME_CID_CONFLICT = 0x0003, - NVME_DATA_TRAS_ERROR = 0x0004, + NVME_DATA_TRANSFER_ERROR = 0x0004, NVME_POWER_LOSS_ABORT = 0x0005, NVME_INTERNAL_DEV_ERROR = 0x0006, NVME_CMD_ABORT_REQ = 0x0007, From patchwork Fri Sep 4 14:19:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 306166 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 4A78FC433E2 for ; Fri, 4 Sep 2020 14:23:19 +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 074E4206B7 for ; Fri, 4 Sep 2020 14:23:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="BhQs9Q08" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 074E4206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:39444 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECcY-0007sm-1D for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:23:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60848) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa0-0002Qx-6g; Fri, 04 Sep 2020 10:20:40 -0400 Received: from charlie.dont.surf ([128.199.63.193]:47882) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZv-0002hN-86; Fri, 04 Sep 2020 10:20:39 -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 2F328BF95B; Fri, 4 Sep 2020 14:20:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229232; bh=7LsDBtn4b9Dn/cGffRm+IPwOtbb/qoXc9QWIQ/78zlg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BhQs9Q089dWrMRmPKGkWAT+D5mvKJuGmcUAU6nX6VoFHw+ejIJyo+PX3d5vEgctoL /KI9oO2RvYOag4HioNikMiWvK13Gp7Aqa6+09H4JB4UkOBltyv8dE2NCfH343SlK2i b2MaavvWFb1vMF63MRDCeGJtpeW6kX2OjsA1CKzYVdMKHdjOaspnaMeTOmmSR/XRdE /AQRfquA6JrkSTYeNIZxW9mD2sGY9bdvRgs5K49g8AROGuToul+rMwYB4635fKUZNR FiICVMKLrNcdnxpx52U0JnD8ftRok3eADwR0zpPzKk9/pzeP+fXH2fqxjDYiBLLm1u 7Qu+352xHXl7w== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 03/17] hw/block/nvme: commonize nvme_rw error handling Date: Fri, 4 Sep 2020 16:19:42 +0200 Message-Id: <20200904141956.576630-4-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Move common error handling to a label. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 49bcdf31ced6..a94e648a80e4 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -687,20 +687,18 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) status = nvme_check_mdts(n, data_size); if (status) { trace_pci_nvme_err_mdts(nvme_cid(req), data_size); - block_acct_invalid(blk_get_stats(n->conf.blk), acct); - return status; + goto invalid; } status = nvme_check_bounds(n, ns, slba, nlb); if (status) { trace_pci_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze); - block_acct_invalid(blk_get_stats(n->conf.blk), acct); - return status; + goto invalid; } - if (nvme_map_dptr(n, data_size, req)) { - block_acct_invalid(blk_get_stats(n->conf.blk), acct); - return NVME_INVALID_FIELD | NVME_DNR; + status = nvme_map_dptr(n, data_size, req); + if (status) { + goto invalid; } if (req->qsg.nsg > 0) { @@ -722,6 +720,10 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) } return NVME_NO_COMPLETE; + +invalid: + block_acct_invalid(blk_get_stats(n->conf.blk), acct); + return status; } static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) From patchwork Fri Sep 4 14:19:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274500 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 25AF1C43461 for ; Fri, 4 Sep 2020 14:21:51 +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 D75C1206B7 for ; Fri, 4 Sep 2020 14:21:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="oYLBM2hn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D75C1206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:60042 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECb8-0004le-0H for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:21:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60826) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZz-0002QI-Cx; Fri, 04 Sep 2020 10:20:39 -0400 Received: from charlie.dont.surf ([128.199.63.193]:47894) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZv-0002hc-BE; Fri, 04 Sep 2020 10:20:39 -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 9F63BBF971; Fri, 4 Sep 2020 14:20:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229232; bh=gogBjjMMi9PEf/7ttP+H9aUwS17DFzWVBvf40kesay4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oYLBM2hnxNyUZM5JV3ZqyjgK3FzxNFqZL8Nf2R9m7AyHBRd4lpn478xACqzRLCYOH 4LlrrSx4Q0gg+va/BEb3O/gUdxXXRyGjQPRtlAAkpYZRLUhkO8Gb3D03uPMWdUf44C B4C9iXTU7F0Q1XHu7LYCkDNoS7AQp9xrgiaSDukBSOfcqq27tZo4i8UoCtUhLBfDrF 94HhbIYVs7lpNaoPGpVjvamBgDygC8iRUcuvMSKd1kug8wtAfTyU+/tpKh1oJdls+1 vXiEcH18fIP4joGGOi1TBmVuxsEFB1u9wQgWspDuWkbbQiyvkWfgtlT+4JF4xvyxZg VfvtMKN/XqStw== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 04/17] hw/block/nvme: alignment style fixes Date: Fri, 4 Sep 2020 16:19:43 +0200 Message-Id: <20200904141956.576630-5-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Style fixes. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index a94e648a80e4..88b4e6288bea 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -634,7 +634,7 @@ static void nvme_rw_cb(void *opaque, int ret) static uint16_t nvme_flush(NvmeCtrl *n, NvmeRequest *req) { block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, - BLOCK_ACCT_FLUSH); + BLOCK_ACCT_FLUSH); req->aiocb = blk_aio_flush(n->conf.blk, nvme_rw_cb, req); return NVME_NO_COMPLETE; @@ -663,7 +663,7 @@ static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, BLOCK_ACCT_WRITE); req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, offset, count, - BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req); + BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req); return NVME_NO_COMPLETE; } @@ -803,7 +803,7 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeRequest *req) } static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, - uint16_t sqid, uint16_t cqid, uint16_t size) + uint16_t sqid, uint16_t cqid, uint16_t size) { int i; NvmeCQueue *cq; @@ -1058,7 +1058,8 @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeRequest *req) } static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr, - uint16_t cqid, uint16_t vector, uint16_t size, uint16_t irq_enabled) + uint16_t cqid, uint16_t vector, uint16_t size, + uint16_t irq_enabled) { int ret; @@ -1118,7 +1119,7 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req) cq = g_malloc0(sizeof(*cq)); nvme_init_cq(cq, n, prp1, cqid, vector, qsize + 1, - NVME_CQ_FLAGS_IEN(qflags)); + NVME_CQ_FLAGS_IEN(qflags)); /* * It is only required to set qs_created when creating a completion queue; @@ -1520,7 +1521,7 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) } if (((n->temperature >= n->features.temp_thresh_hi) || - (n->temperature <= n->features.temp_thresh_low)) && + (n->temperature <= n->features.temp_thresh_low)) && NVME_AEC_SMART(n->features.async_config) & NVME_SMART_TEMPERATURE) { nvme_enqueue_event(n, NVME_AER_TYPE_SMART, NVME_AER_INFO_SMART_TEMP_THRESH, @@ -1770,9 +1771,9 @@ static int nvme_start_ctrl(NvmeCtrl *n) n->cqe_size = 1 << NVME_CC_IOCQES(n->bar.cc); n->sqe_size = 1 << NVME_CC_IOSQES(n->bar.cc); nvme_init_cq(&n->admin_cq, n, n->bar.acq, 0, 0, - NVME_AQA_ACQS(n->bar.aqa) + 1, 1); + NVME_AQA_ACQS(n->bar.aqa) + 1, 1); nvme_init_sq(&n->admin_sq, n, n->bar.asq, 0, 0, - NVME_AQA_ASQS(n->bar.aqa) + 1); + NVME_AQA_ASQS(n->bar.aqa) + 1); nvme_set_timestamp(n, 0ULL); @@ -1782,7 +1783,7 @@ static int nvme_start_ctrl(NvmeCtrl *n) } static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, - unsigned size) + unsigned size) { if (unlikely(offset & (sizeof(uint32_t) - 1))) { NVME_GUEST_ERR(pci_nvme_ub_mmiowr_misaligned32, @@ -1925,7 +1926,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, "invalid write to PMRSWTP register, ignored"); return; case 0xE14: /* TODO PMRMSC */ - break; + break; default: NVME_GUEST_ERR(pci_nvme_ub_mmiowr_invalid, "invalid MMIO write," @@ -2101,7 +2102,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) } static void nvme_mmio_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) + unsigned size) { NvmeCtrl *n = (NvmeCtrl *)opaque; @@ -2125,7 +2126,7 @@ static const MemoryRegionOps nvme_mmio_ops = { }; static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) + unsigned size) { NvmeCtrl *n = (NvmeCtrl *)opaque; stn_le_p(&n->cmbuf[addr], size, data); From patchwork Fri Sep 4 14:19:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 306167 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 462B0C43461 for ; Fri, 4 Sep 2020 14:21:44 +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 F0F5E206B7 for ; Fri, 4 Sep 2020 14:21:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="eh7ZDZbi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F0F5E206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:59320 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECb0-0004Sk-Vr for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:21:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60860) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa0-0002RK-LB; Fri, 04 Sep 2020 10:20:40 -0400 Received: from charlie.dont.surf ([128.199.63.193]:47986) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZy-0002ia-UN; Fri, 04 Sep 2020 10:20:40 -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 01C49BFA7A; Fri, 4 Sep 2020 14:20:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229233; bh=x5rI1HWixO9M3U5Sx5ljE1KG3wqn4Or/3ScwW+wMAzc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eh7ZDZbiwq8glXSnUVwUhnWjtI6V+OjLIMxHs9v0j3en+gDx5kPi1q3VhLsnHpnER p3pXEO+aeKQKkijRSq6w0THFuZDRZYynjDyjYahvIKCvrPrrKhplXfvuu9SbdHpb2t EJHm/dLdNfyIMRI8lFAZ1HyabGdqL8cD2aGNZ12RowWDOB4eSIFP5+3UpEOKaO0vsP WkdTObRy7mv/G7KTrjszHtsXv+b8IQFHxT33eDpyvHvxHyRGJvwr+GWJgJRDWKG4Xh jvjS9J4jS9bJvzxOQ77IU8a0obiCRnJeQZAHleljbSRUOWYrj3x28P4ZJaGBH/nkUP qt3485TbdM5Rw== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 05/17] hw/block/nvme: add a lba to bytes helper Date: Fri, 4 Sep 2020 16:19:44 +0200 Message-Id: <20200904141956.576630-6-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add the nvme_l2b helper and use it for converting NLB and SLBA to byte counts and offsets. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 12 ++++-------- hw/block/nvme.h | 6 ++++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 88b4e6288bea..08f824dd807d 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -644,12 +644,10 @@ static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; - const uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); - const uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; - uint64_t offset = slba << data_shift; - uint32_t count = nlb << data_shift; + uint64_t offset = nvme_l2b(ns, slba); + uint32_t count = nvme_l2b(ns, nlb); uint16_t status; trace_pci_nvme_write_zeroes(nvme_cid(req), slba, nlb); @@ -674,10 +672,8 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) uint32_t nlb = le32_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); - uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); - uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds; - uint64_t data_size = (uint64_t)nlb << data_shift; - uint64_t data_offset = slba << data_shift; + uint64_t data_size = nvme_l2b(ns, nlb); + uint64_t data_offset = nvme_l2b(ns, slba); int is_write = rw->opcode == NVME_CMD_WRITE ? 1 : 0; enum BlockAcctType acct = is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ; uint16_t status; diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 52ba794f2e9a..1675c1e0755c 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -77,6 +77,12 @@ static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns) return nvme_ns_lbaf(ns)->ds; } +/* convert an LBA to the equivalent in bytes */ +static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) +{ + return lba << nvme_ns_lbads(ns); +} + #define TYPE_NVME "nvme" #define NVME(obj) \ OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) From patchwork Fri Sep 4 14:19:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274498 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 44A4BC433E2 for ; Fri, 4 Sep 2020 14:24:45 +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 0130D206B7 for ; Fri, 4 Sep 2020 14:24:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="QX4jBVAM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0130D206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:47826 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECdw-00030Z-40 for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:24:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60874) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa1-0002Sv-Al; Fri, 04 Sep 2020 10:20:41 -0400 Received: from charlie.dont.surf ([128.199.63.193]:47988) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECZy-0002ib-Um; Fri, 04 Sep 2020 10:20:40 -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 58BC9BFADA; Fri, 4 Sep 2020 14:20:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229233; bh=N75pEHGwe0j3jOW0KRkVA1wliaihAHhbFGlpZBmtj/4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QX4jBVAMWHYNWxnkk9nNh/OkCmyRal3Bjvde4bA4efFFu/4gozzlnBjcvrgrPUcFr eVXkcOmwd7UmMsOlao/O625yA64+amgVo9GBy+SI7h21leT7LjlmDSOfkUpjetwVoP kftxb3EmuAJVcWrsem2GBz92CTfTqAwJHGPxkKJNXNH/P/hg34qYMTaaOs1+OoPSat JbEPwvNSGzDLRfcQyZFuap9SK2CFex43hV63ri1hU1HpGCqjEFUsbuACv7y009eiKF k9RMqFYX44dC8Bepml3LfJOcIPesczLNzuLX6Hw9plwIU2yMBOhMIWbvIlq7/lYN6c yWfVAf+lDs4Lg== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 06/17] hw/block/nvme: fix endian conversion Date: Fri, 4 Sep 2020 16:19:45 +0200 Message-Id: <20200904141956.576630-7-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen The raw NLB field is a 16 bit value, so use le16_to_cpu instead of le32_to_cpu and cast to uint32_t before incrementing the value to not wrap around. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 08f824dd807d..50851ab8d90f 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -645,7 +645,7 @@ static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; uint64_t slba = le64_to_cpu(rw->slba); - uint32_t nlb = le16_to_cpu(rw->nlb) + 1; + uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint64_t offset = nvme_l2b(ns, slba); uint32_t count = nvme_l2b(ns, nlb); uint16_t status; @@ -669,7 +669,7 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; - uint32_t nlb = le32_to_cpu(rw->nlb) + 1; + uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); uint64_t data_size = nvme_l2b(ns, nlb); From patchwork Fri Sep 4 14:19: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: 306164 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 822EFC43461 for ; Fri, 4 Sep 2020 14:24:53 +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 3F8C5206B7 for ; Fri, 4 Sep 2020 14:24:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="O8jjXVUu" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3F8C5206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:48668 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECe4-0003Mc-Bk for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:24:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60894) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa2-0002Vt-Gg; Fri, 04 Sep 2020 10:20:42 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48016) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa0-0002j2-8M; Fri, 04 Sep 2020 10:20:41 -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 B0179BFAF0; Fri, 4 Sep 2020 14:20:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229234; bh=8cywTxdJhyqSkNSvFGd2rjU28gIcQiKnhrDu2RCnUZE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=O8jjXVUuUzgx6JJ+J9R0ZEtKbFrRWBZTWUyv20KSVUlMXv1BTPzvuhbWw3uVLIxbZ 5iKZwyfyVJMKE+la+hWrPNh35FfSQP74B7qWalB0tsJ1jWCVcRPZnLmK++oP22Yxgh hNGG1f5WEAGcqbmZUZ8HWZJRKFi3Wo74CeRy/KFtd6xxWJGOaQBj+QSiqsbtnXJQd6 Y53bcfdw2DMrVuDrX9YVniYDCRlbk0/9t83c+Ndn6xrt5jzNRWSiwrkNwuZxJv2oEZ 7o1pmcYfNMKCS9JVolYFs7ZTDyNrI9Uh+JFcmCa4aZFxFBcCiSJHPOUf4QjWm5k/+n Eq8O4W0IxRArg== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 07/17] hw/block/nvme: add symbolic command name to trace events Date: Fri, 4 Sep 2020 16:19:46 +0200 Message-Id: <20200904141956.576630-8-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add the symbolic command name to the pci_nvme_{io,admin}_cmd and pci_nvme_rw trace events. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 8 +++++--- hw/block/nvme.h | 28 ++++++++++++++++++++++++++++ hw/block/trace-events | 6 +++--- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 50851ab8d90f..bfac3385cb64 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -678,7 +678,8 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) enum BlockAcctType acct = is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ; uint16_t status; - trace_pci_nvme_rw(is_write ? "write" : "read", nlb, data_size, slba); + trace_pci_nvme_rw(nvme_cid(req), nvme_io_opc_str(rw->opcode), nlb, + data_size, slba); status = nvme_check_mdts(n, data_size); if (status) { @@ -727,7 +728,7 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) uint32_t nsid = le32_to_cpu(req->cmd.nsid); trace_pci_nvme_io_cmd(nvme_cid(req), nsid, nvme_sqid(req), - req->cmd.opcode); + req->cmd.opcode, nvme_io_opc_str(req->cmd.opcode)); if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces); @@ -1584,7 +1585,8 @@ static uint16_t nvme_aer(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req) { - trace_pci_nvme_admin_cmd(nvme_cid(req), nvme_sqid(req), req->cmd.opcode); + trace_pci_nvme_admin_cmd(nvme_cid(req), nvme_sqid(req), req->cmd.opcode, + nvme_adm_opc_str(req->cmd.opcode)); switch (req->cmd.opcode) { case NVME_ADM_CMD_DELETE_SQ: diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 1675c1e0755c..ce9e931420d7 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -32,6 +32,34 @@ typedef struct NvmeRequest { QTAILQ_ENTRY(NvmeRequest)entry; } NvmeRequest; +static inline const char *nvme_adm_opc_str(uint8_t opc) +{ + switch (opc) { + case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ"; + case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ"; + case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE"; + case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ"; + case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ"; + case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY"; + case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT"; + case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES"; + case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES"; + case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ"; + default: return "NVME_ADM_CMD_UNKNOWN"; + } +} + +static inline const char *nvme_io_opc_str(uint8_t opc) +{ + switch (opc) { + case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH"; + case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE"; + case NVME_CMD_READ: return "NVME_NVM_CMD_READ"; + case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES"; + default: return "NVME_NVM_CMD_UNKNOWN"; + } +} + typedef struct NvmeSQueue { struct NvmeCtrl *ctrl; uint16_t sqid; diff --git a/hw/block/trace-events b/hw/block/trace-events index 50d5702e6b80..0823d0fb47c5 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -36,9 +36,9 @@ pci_nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2 pci_nvme_map_addr(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64"" pci_nvme_map_addr_cmb(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64"" pci_nvme_map_prp(uint64_t trans_len, uint32_t len, uint64_t prp1, uint64_t prp2, int num_prps) "trans_len %"PRIu64" len %"PRIu32" prp1 0x%"PRIx64" prp2 0x%"PRIx64" num_prps %d" -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_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" +pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" +pci_nvme_rw(uint16_t cid, const char *verb, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" \"%s\" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64"" 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"" From patchwork Fri Sep 4 14:19:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274496 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 93673C433E2 for ; Fri, 4 Sep 2020 14:26: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 35FC2206B7 for ; Fri, 4 Sep 2020 14:26:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="ghIzXHlH" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 35FC2206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:56782 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECfv-0006pN-9S for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:26:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60898) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa2-0002X7-R4; Fri, 04 Sep 2020 10:20:42 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48018) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa0-0002j1-5Q; Fri, 04 Sep 2020 10:20:42 -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 1644DBFAF8; Fri, 4 Sep 2020 14:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229234; bh=o9LhlPSuEq62L2IPIXUW56rb6l9LYLLXVqfjyEEIlfk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ghIzXHlH9OLq8d9X1tUr6e3fLSphsVhGizoinapk95F05eo0hL3riqL4uzxqZEwEd m/+Q7mmNIHWJMkBlDHatPMJY6IKql6Hw7bvbaYwYzfNnmZTQguo0vq7Xe+z0YRI4qf VjjKXLXjjUbpA+XyYhdThGO5jnupwZmXXSYSzVNzN+wYl1xbHQN/mIS+puTlrWFloY k6HaVykx+ePPxbzb1vMOlWfwwnQ0uIoAyf1I4TcHIt7pJnaqQo9bUtiutF+xhgCFFl dAbCbRJJK5edoq54HBcf2sK7tR7594xmk+FuDntYssMSruPa6vvw1rbavOy3FQ8Zvq JvQZIScrUL7pg== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 08/17] hw/block/nvme: refactor aio submission Date: Fri, 4 Sep 2020 16:19:47 +0200 Message-Id: <20200904141956.576630-9-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen This pulls block layer aio submission to a common function an introduces the NvmeAIO structure that encapsulates this. This adds more code with no immediate benefit, but is in preparation for supporting multiple aios per request. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 191 ++++++++++++++++++++++++++++++++---------- hw/block/nvme.h | 51 +++++++++++ hw/block/trace-events | 3 + 3 files changed, 203 insertions(+), 42 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index bfac3385cb64..3e32f39c7c1d 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -110,6 +110,7 @@ static const uint32_t nvme_feature_cap[NVME_FID_MAX] = { }; static void nvme_process_sq(void *opaque); +static void nvme_aio_cb(void *opaque, int ret); static uint16_t nvme_cid(NvmeRequest *req) { @@ -611,39 +612,151 @@ static inline uint16_t nvme_check_bounds(NvmeCtrl *n, NvmeNamespace *ns, return NVME_SUCCESS; } -static void nvme_rw_cb(void *opaque, int ret) +static NvmeAIO *nvme_aio_new(NvmeAIOOp opc, BlockBackend *blk, int64_t offset) { - NvmeRequest *req = opaque; - NvmeSQueue *sq = req->sq; - NvmeCtrl *n = sq->ctrl; - NvmeCQueue *cq = n->cq[sq->cqid]; + NvmeAIO *aio = g_new0(NvmeAIO, 1); - trace_pci_nvme_rw_cb(nvme_cid(req)); + aio->opc = opc; + aio->blk = blk; + aio->offset = offset; - if (!ret) { - block_acct_done(blk_get_stats(n->conf.blk), &req->acct); - req->status = NVME_SUCCESS; - } else { - block_acct_failed(blk_get_stats(n->conf.blk), &req->acct); - req->status = NVME_INTERNAL_DEV_ERROR; + return aio; +} + +static void nvme_aio_destroy(NvmeAIO *aio) +{ + g_free(aio); +} + +static uint16_t nvme_do_aio(NvmeAIO *aio) +{ + NvmeRequest *req = aio->req; + + BlockBackend *blk = aio->blk; + BlockAcctCookie *acct = &req->acct; + BlockAcctStats *stats = blk_get_stats(blk); + + bool is_write; + + switch (aio->opc) { + case NVME_AIO_OPC_FLUSH: + block_acct_start(stats, acct, 0, BLOCK_ACCT_FLUSH); + req->aiocb = blk_aio_flush(blk, nvme_aio_cb, aio); + break; + + case NVME_AIO_OPC_WRITE_ZEROES: + block_acct_start(stats, acct, aio->len, BLOCK_ACCT_WRITE); + req->aiocb = blk_aio_pwrite_zeroes(blk, aio->offset, aio->len, + BDRV_REQ_MAY_UNMAP, nvme_aio_cb, + aio); + break; + + case NVME_AIO_OPC_READ: + case NVME_AIO_OPC_WRITE: + is_write = (aio->opc == NVME_AIO_OPC_WRITE); + + block_acct_start(stats, acct, aio->len, + is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ); + + if (aio->flags & NVME_AIO_DMA) { + QEMUSGList *qsg = (QEMUSGList *)aio->payload; + + if (is_write) { + req->aiocb = dma_blk_write(blk, qsg, aio->offset, + BDRV_SECTOR_SIZE, nvme_aio_cb, aio); + } else { + req->aiocb = dma_blk_read(blk, qsg, aio->offset, + BDRV_SECTOR_SIZE, nvme_aio_cb, aio); + } + } else { + QEMUIOVector *iov = (QEMUIOVector *)aio->payload; + + if (is_write) { + req->aiocb = blk_aio_pwritev(blk, aio->offset, iov, 0, + nvme_aio_cb, aio); + } else { + req->aiocb = blk_aio_preadv(blk, aio->offset, iov, 0, + nvme_aio_cb, aio); + } + } + + break; } - nvme_enqueue_req_completion(cq, req); + return NVME_NO_COMPLETE; +} + +static uint16_t nvme_aio_add(NvmeRequest *req, NvmeAIO *aio) +{ + aio->req = req; + + trace_pci_nvme_aio_add(nvme_cid(req), aio, blk_name(aio->blk), + aio->offset, aio->len, nvme_aio_opc_str(aio), + req); + + return nvme_do_aio(aio); +} + +static void nvme_aio_cb(void *opaque, int ret) +{ + NvmeAIO *aio = opaque; + NvmeRequest *req = aio->req; + + BlockBackend *blk = aio->blk; + BlockAcctCookie *acct = &req->acct; + BlockAcctStats *stats = blk_get_stats(blk); + + Error *local_err = NULL; + + trace_pci_nvme_aio_cb(nvme_cid(req), aio, blk_name(blk), aio->offset, + aio->len, nvme_aio_opc_str(aio), req); + + if (!ret) { + block_acct_done(stats, acct); + req->status = NVME_SUCCESS; + } else { + uint16_t status; + + block_acct_failed(stats, acct); + + switch (aio->opc) { + case NVME_AIO_OPC_READ: + status = NVME_UNRECOVERED_READ; + break; + case NVME_AIO_OPC_FLUSH: + case NVME_AIO_OPC_WRITE: + case NVME_AIO_OPC_WRITE_ZEROES: + status = NVME_WRITE_FAULT; + break; + default: + status = NVME_INTERNAL_DEV_ERROR; + break; + } + + trace_pci_nvme_err_aio(nvme_cid(req), aio, blk_name(blk), + aio->offset, nvme_aio_opc_str(aio), req, + status); + + error_setg_errno(&local_err, -ret, "aio failed"); + error_report_err(local_err); + + req->status = status; + } + + nvme_enqueue_req_completion(nvme_cq(req), req); + nvme_aio_destroy(aio); } static uint16_t nvme_flush(NvmeCtrl *n, NvmeRequest *req) { - block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, - BLOCK_ACCT_FLUSH); - req->aiocb = blk_aio_flush(n->conf.blk, nvme_rw_cb, req); - - return NVME_NO_COMPLETE; + return nvme_aio_add(req, nvme_aio_new(NVME_AIO_OPC_FLUSH, n->conf.blk, 0)); } static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeAIO *aio; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint64_t offset = nvme_l2b(ns, slba); @@ -658,24 +771,23 @@ static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) return status; } - block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, - BLOCK_ACCT_WRITE); - req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, offset, count, - BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req); - return NVME_NO_COMPLETE; + aio = nvme_aio_new(NVME_AIO_OPC_WRITE_ZEROES, n->conf.blk, offset); + aio->len = count; + + return nvme_aio_add(req, aio); } static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeAIO *aio; uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); uint64_t data_size = nvme_l2b(ns, nlb); uint64_t data_offset = nvme_l2b(ns, slba); - int is_write = rw->opcode == NVME_CMD_WRITE ? 1 : 0; - enum BlockAcctType acct = is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ; + bool is_write = nvme_req_is_write(req); uint16_t status; trace_pci_nvme_rw(nvme_cid(req), nvme_io_opc_str(rw->opcode), nlb, @@ -698,28 +810,23 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) goto invalid; } - if (req->qsg.nsg > 0) { - block_acct_start(blk_get_stats(n->conf.blk), &req->acct, req->qsg.size, - acct); - req->aiocb = is_write ? - dma_blk_write(n->conf.blk, &req->qsg, data_offset, BDRV_SECTOR_SIZE, - nvme_rw_cb, req) : - dma_blk_read(n->conf.blk, &req->qsg, data_offset, BDRV_SECTOR_SIZE, - nvme_rw_cb, req); + aio = nvme_aio_new(is_write ? NVME_AIO_OPC_WRITE : NVME_AIO_OPC_READ, + n->conf.blk, data_offset); + + if (req->qsg.sg) { + aio->payload = &req->qsg; + aio->len = req->qsg.size; + aio->flags |= NVME_AIO_DMA; } else { - block_acct_start(blk_get_stats(n->conf.blk), &req->acct, req->iov.size, - acct); - req->aiocb = is_write ? - blk_aio_pwritev(n->conf.blk, data_offset, &req->iov, 0, nvme_rw_cb, - req) : - blk_aio_preadv(n->conf.blk, data_offset, &req->iov, 0, nvme_rw_cb, - req); + aio->payload = &req->iov; + aio->len = req->iov.size; } - return NVME_NO_COMPLETE; + return nvme_aio_add(req, aio); invalid: - block_acct_invalid(blk_get_stats(n->conf.blk), acct); + block_acct_invalid(blk_get_stats(n->conf.blk), + is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ); return status; } diff --git a/hw/block/nvme.h b/hw/block/nvme.h index ce9e931420d7..7a11b0b37317 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -32,6 +32,17 @@ typedef struct NvmeRequest { QTAILQ_ENTRY(NvmeRequest)entry; } NvmeRequest; +static inline bool nvme_req_is_write(NvmeRequest *req) +{ + switch (req->cmd.opcode) { + case NVME_CMD_WRITE: + case NVME_CMD_WRITE_ZEROES: + return true; + default: + return false; + } +} + static inline const char *nvme_adm_opc_str(uint8_t opc) { switch (opc) { @@ -60,6 +71,38 @@ static inline const char *nvme_io_opc_str(uint8_t opc) } } +typedef enum NvmeAIOOp { + NVME_AIO_OPC_FLUSH = 0x1, + NVME_AIO_OPC_READ = 0x2, + NVME_AIO_OPC_WRITE = 0x3, + NVME_AIO_OPC_WRITE_ZEROES = 0x4, +} NvmeAIOOp; + +typedef enum NvmeAIOFlags { + NVME_AIO_DMA = 1 << 0, +} NvmeAIOFlags; + +typedef struct NvmeAIO { + NvmeAIOOp opc; + NvmeRequest *req; + BlockBackend *blk; + int64_t offset; + size_t len; + int flags; + void *payload; +} NvmeAIO; + +static inline const char *nvme_aio_opc_str(NvmeAIO *aio) +{ + switch (aio->opc) { + case NVME_AIO_OPC_FLUSH: return "NVME_AIO_OPC_FLUSH"; + case NVME_AIO_OPC_READ: return "NVME_AIO_OPC_READ"; + case NVME_AIO_OPC_WRITE: return "NVME_AIO_OPC_WRITE"; + case NVME_AIO_OPC_WRITE_ZEROES: return "NVME_AIO_OPC_WRITE_ZEROES"; + default: return "NVME_AIO_OPC_UNKNOWN"; + } +} + typedef struct NvmeSQueue { struct NvmeCtrl *ctrl; uint16_t sqid; @@ -171,4 +214,12 @@ static inline uint64_t nvme_ns_nlbas(NvmeCtrl *n, NvmeNamespace *ns) return n->ns_size >> nvme_ns_lbads(ns); } +static inline NvmeCQueue *nvme_cq(NvmeRequest *req) +{ + NvmeSQueue *sq = req->sq; + NvmeCtrl *n = sq->ctrl; + + return n->cq[sq->cqid]; +} + #endif /* HW_NVME_H */ diff --git a/hw/block/trace-events b/hw/block/trace-events index 0823d0fb47c5..fb3bf1be5e07 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -39,6 +39,8 @@ pci_nvme_map_prp(uint64_t trans_len, uint32_t len, uint64_t prp1, uint64_t prp2, pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" pci_nvme_rw(uint16_t cid, const char *verb, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" \"%s\" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64"" +pci_nvme_aio_add(uint16_t cid, void *aio, const char *blkname, uint64_t offset, uint64_t len, const char *opc, void *req) "cid %"PRIu16" aio %p blk \"%s\" offset %"PRIu64" len %"PRIu64" opc \"%s\" req %p" +pci_nvme_aio_cb(uint16_t cid, void *aio, const char *blkname, uint64_t offset, uint64_t len, const char *opc, void *req) "cid %"PRIu16" aio %p blk \"%s\" offset %"PRIu64" len %"PRIu64" opc \"%s\" req %p" 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"" @@ -88,6 +90,7 @@ pci_nvme_mmio_shutdown_cleared(void) "shutdown bit cleared" pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu" pci_nvme_err_addr_read(uint64_t addr) "addr 0x%"PRIx64"" pci_nvme_err_addr_write(uint64_t addr) "addr 0x%"PRIx64"" +pci_nvme_err_aio(uint16_t cid, void *aio, const char *blkname, uint64_t offset, const char *opc, void *req, uint16_t status) "cid %"PRIu16" aio %p blk \"%s\" offset %"PRIu64" opc \"%s\" req %p status 0x%"PRIx16"" pci_nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size" pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or not page aligned: 0x%"PRIx64"" pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64"" From patchwork Fri Sep 4 14:19: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: 306162 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 9BA75C2BB84 for ; Fri, 4 Sep 2020 14:26:54 +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 5C131206B7 for ; Fri, 4 Sep 2020 14:26:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="d202gZnC" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5C131206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:57528 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECg1-00077f-EN for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:26:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32792) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaM-0003Mm-HH; Fri, 04 Sep 2020 10:21:02 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48020) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaK-0002jC-M7; Fri, 04 Sep 2020 10:21:02 -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 6ECC3BFAFF; Fri, 4 Sep 2020 14:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229234; bh=ghTHzL0RGC/yyl0C9NlaoYrGykOslGwT28dRWldXulQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d202gZnCwAOlL/ykE0opM+Iadinc+JeMZPfEi81ds9GlG/gB0yWPpEs9BwKonhfNX xBQkSWlaQhBl56vVvwIeqVQbEAcECdFmtOn9dkUEoDAqQ2yBzfqf0E5lMgqNgG5hOz ShHD+xJeI5mrru3EHc0rk0tpovU1UpU4mEr0gdEg/Zn4IdQMnmroCyZmn3CC9//VQd 5sWapkp5xAU+EtgiDMAwcB8ASDILOybQtYT1FOqcxzwbEGbAvFWSSC86ySJcKyaAb2 pmGbKhIAEAWPwF+Bs7k99LdPJE2xnmDRFCngdbTvp522MnKxEyyvxmAtqzN+Cvlxm3 uVlRgndplfw/Q== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 09/17] hw/block/nvme: default request status to success Date: Fri, 4 Sep 2020 16:19:48 +0200 Message-Id: <20200904141956.576630-10-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Make the default request status NVME_SUCCESS so only error status codes has to be set. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 3e32f39c7c1d..64c8f232e3ea 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -231,6 +231,7 @@ static void nvme_req_clear(NvmeRequest *req) { req->ns = NULL; memset(&req->cqe, 0x0, sizeof(req->cqe)); + req->status = NVME_SUCCESS; } static void nvme_req_exit(NvmeRequest *req) @@ -547,8 +548,6 @@ static void nvme_process_aers(void *opaque) result->log_page = event->result.log_page; g_free(event); - req->status = NVME_SUCCESS; - trace_pci_nvme_aer_post_cqe(result->event_type, result->event_info, result->log_page); @@ -713,7 +712,6 @@ static void nvme_aio_cb(void *opaque, int ret) if (!ret) { block_acct_done(stats, acct); - req->status = NVME_SUCCESS; } else { uint16_t status; From patchwork Fri Sep 4 14:19: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: 306161 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 0D5B3C43461 for ; Fri, 4 Sep 2020 14:28:45 +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 C2A7D206B8 for ; Fri, 4 Sep 2020 14:28:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="IxrQUm89" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C2A7D206B8 Authentication-Results: mail.kernel.org; dmarc=fail (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]:36942 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kEChm-0001o5-BD for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:28:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60906) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa3-0002Xm-3P; Fri, 04 Sep 2020 10:20:43 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48022) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECa0-0002j9-Hc; Fri, 04 Sep 2020 10:20:42 -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 C6F6FBFB07; Fri, 4 Sep 2020 14:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229235; bh=kq9SZ7rxoSp0pOdHatuuNolGXaFd09h9ScnJjZG7sWM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IxrQUm89KYDz8wsutcBMQ3WUaEk2UkMiy+FQ0Q+QFAVqT1ycwkilsi/qssK5bBul5 /9A1cxWso/bsOipS79gbf4wTjS/rH9sC3+PtOckhdMtbiYWRuIHthWJvrSTqtwW6KD nMpG0+ViARS/LKWU2xT2D7K4D93cGj192uSsAgjm81TOEgzf/pEr7mOBPi5/JHOBH9 2Afo6GkrMqkJB34bh1fn8ohJH2xbBYALZzf+yyftBRfpOP/k6A1zHE3BzOWt3Qb5Lq +PjZp3RdY+pvEDVM/a8AvjpujgHzG6lGmVD9yzrVCdi8km4q3aXLjef3gvgoAdfFhR Ss9AP65KNmhzQ== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 10/17] hw/block/nvme: support multiple parallel aios per request Date: Fri, 4 Sep 2020 16:19:49 +0200 Message-Id: <20200904141956.576630-11-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Move the BlockAIOCB to NvmeAIO and add a queue of pending AIOs to the NvmeRequest. Only when the queue is empty is a completion enqueued. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 44 ++++++++++++++++++++++++++++++-------------- hw/block/nvme.h | 6 ++++-- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 64c8f232e3ea..36ec8cbb1168 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -629,10 +629,8 @@ static void nvme_aio_destroy(NvmeAIO *aio) static uint16_t nvme_do_aio(NvmeAIO *aio) { - NvmeRequest *req = aio->req; - BlockBackend *blk = aio->blk; - BlockAcctCookie *acct = &req->acct; + BlockAcctCookie *acct = &aio->acct; BlockAcctStats *stats = blk_get_stats(blk); bool is_write; @@ -640,12 +638,12 @@ static uint16_t nvme_do_aio(NvmeAIO *aio) switch (aio->opc) { case NVME_AIO_OPC_FLUSH: block_acct_start(stats, acct, 0, BLOCK_ACCT_FLUSH); - req->aiocb = blk_aio_flush(blk, nvme_aio_cb, aio); + aio->aiocb = blk_aio_flush(blk, nvme_aio_cb, aio); break; case NVME_AIO_OPC_WRITE_ZEROES: block_acct_start(stats, acct, aio->len, BLOCK_ACCT_WRITE); - req->aiocb = blk_aio_pwrite_zeroes(blk, aio->offset, aio->len, + aio->aiocb = blk_aio_pwrite_zeroes(blk, aio->offset, aio->len, BDRV_REQ_MAY_UNMAP, nvme_aio_cb, aio); break; @@ -661,20 +659,20 @@ static uint16_t nvme_do_aio(NvmeAIO *aio) QEMUSGList *qsg = (QEMUSGList *)aio->payload; if (is_write) { - req->aiocb = dma_blk_write(blk, qsg, aio->offset, + aio->aiocb = dma_blk_write(blk, qsg, aio->offset, BDRV_SECTOR_SIZE, nvme_aio_cb, aio); } else { - req->aiocb = dma_blk_read(blk, qsg, aio->offset, + aio->aiocb = dma_blk_read(blk, qsg, aio->offset, BDRV_SECTOR_SIZE, nvme_aio_cb, aio); } } else { QEMUIOVector *iov = (QEMUIOVector *)aio->payload; if (is_write) { - req->aiocb = blk_aio_pwritev(blk, aio->offset, iov, 0, + aio->aiocb = blk_aio_pwritev(blk, aio->offset, iov, 0, nvme_aio_cb, aio); } else { - req->aiocb = blk_aio_preadv(blk, aio->offset, iov, 0, + aio->aiocb = blk_aio_preadv(blk, aio->offset, iov, 0, nvme_aio_cb, aio); } } @@ -693,6 +691,8 @@ static uint16_t nvme_aio_add(NvmeRequest *req, NvmeAIO *aio) aio->offset, aio->len, nvme_aio_opc_str(aio), req); + QTAILQ_INSERT_TAIL(&req->aio_tailq, aio, entry); + return nvme_do_aio(aio); } @@ -702,7 +702,7 @@ static void nvme_aio_cb(void *opaque, int ret) NvmeRequest *req = aio->req; BlockBackend *blk = aio->blk; - BlockAcctCookie *acct = &req->acct; + BlockAcctCookie *acct = &aio->acct; BlockAcctStats *stats = blk_get_stats(blk); Error *local_err = NULL; @@ -710,6 +710,8 @@ static void nvme_aio_cb(void *opaque, int ret) trace_pci_nvme_aio_cb(nvme_cid(req), aio, blk_name(blk), aio->offset, aio->len, nvme_aio_opc_str(aio), req); + QTAILQ_REMOVE(&req->aio_tailq, aio, entry); + if (!ret) { block_acct_done(stats, acct); } else { @@ -738,10 +740,19 @@ static void nvme_aio_cb(void *opaque, int ret) error_setg_errno(&local_err, -ret, "aio failed"); error_report_err(local_err); - req->status = status; + /* + * An Internal Error trumps all other errors. For other errors, only + * set the first encountered. + */ + if (!req->status || (status & 0xfff) == NVME_INTERNAL_DEV_ERROR) { + req->status = status; + } + } + + if (QTAILQ_EMPTY(&req->aio_tailq)) { + nvme_enqueue_req_completion(nvme_cq(req), req); } - nvme_enqueue_req_completion(nvme_cq(req), req); nvme_aio_destroy(aio); } @@ -872,6 +883,7 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeRequest *req) NvmeRequest *r, *next; NvmeSQueue *sq; NvmeCQueue *cq; + NvmeAIO *aio; uint16_t qid = le16_to_cpu(c->qid); if (unlikely(!qid || nvme_check_sqid(n, qid))) { @@ -884,8 +896,11 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeRequest *req) sq = n->sq[qid]; while (!QTAILQ_EMPTY(&sq->out_req_list)) { r = QTAILQ_FIRST(&sq->out_req_list); - assert(r->aiocb); - blk_aio_cancel(r->aiocb); + while (!QTAILQ_EMPTY(&r->aio_tailq)) { + aio = QTAILQ_FIRST(&r->aio_tailq); + assert(aio->aiocb); + blk_aio_cancel(aio->aiocb); + } } if (!nvme_check_cqid(n, sq->cqid)) { cq = n->cq[sq->cqid]; @@ -923,6 +938,7 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, for (i = 0; i < sq->size; i++) { sq->io_req[i].sq = sq; QTAILQ_INSERT_TAIL(&(sq->req_list), &sq->io_req[i], entry); + QTAILQ_INIT(&(sq->io_req[i].aio_tailq)); } sq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_process_sq, sq); diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 7a11b0b37317..baedcb226cb1 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -22,14 +22,13 @@ typedef struct NvmeAsyncEvent { typedef struct NvmeRequest { struct NvmeSQueue *sq; struct NvmeNamespace *ns; - BlockAIOCB *aiocb; uint16_t status; NvmeCqe cqe; NvmeCmd cmd; - BlockAcctCookie acct; QEMUSGList qsg; QEMUIOVector iov; QTAILQ_ENTRY(NvmeRequest)entry; + QTAILQ_HEAD(, NvmeAIO) aio_tailq; } NvmeRequest; static inline bool nvme_req_is_write(NvmeRequest *req) @@ -86,10 +85,13 @@ typedef struct NvmeAIO { NvmeAIOOp opc; NvmeRequest *req; BlockBackend *blk; + BlockAcctCookie acct; + BlockAIOCB *aiocb; int64_t offset; size_t len; int flags; void *payload; + QTAILQ_ENTRY(NvmeAIO) entry; } NvmeAIO; static inline const char *nvme_aio_opc_str(NvmeAIO *aio) From patchwork Fri Sep 4 14:19: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: 306163 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 8E970C433E2 for ; Fri, 4 Sep 2020 14:25:25 +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 4CE71206B7 for ; Fri, 4 Sep 2020 14:25:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="e/sQO1Mt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4CE71206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:51048 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECea-0004Jq-GA for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:25:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32830) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaN-0003Qa-UA; Fri, 04 Sep 2020 10:21:03 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48026) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaK-0002jO-UY; Fri, 04 Sep 2020 10:21:03 -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 28CDFBFB11; Fri, 4 Sep 2020 14:20:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229235; bh=EQ+4R5Vy/UfJdr5yFK7JiK6m8tq6GI0f6UYFm4P+Xfo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e/sQO1MtL8CasgfXqaY82NXNFAXcaB4R2FIsUdrJ57RC5LMD2CUIev5SHcaRj3Qd8 gFim2PafLrQ+YUfYX0tenI1iTXigqi8m/sJ8hQgJvq3sAq6ruwhBGJwtLS+MoxSXZO ny2T05P8H56FASZQfREYuM95UnynP9KvQ4s38BDuyUXi9J6B/yk48J3mH0K1d4MXGa DvpRw//GnqmFjgzqpBI12HMvrjc9ZEbpQXyz6t6kiQlSZI2oErqYzL4xrOhiH3Wksk cZxUf4UjScm2OO0IDMWY3zHZw644eN7xcOdqxI2NlvHhwznoWwqkDvF4UTfWyx6dq5 HeFxCF6lI7zng== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 11/17] hw/block/nvme: harden cmb access Date: Fri, 4 Sep 2020 16:19:50 +0200 Message-Id: <20200904141956.576630-12-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Since the controller has only supported PRPs so far it has not been required to check the ending address (addr + len - 1) of the CMB access for validity since it has been guaranteed to be in range of the CMB. This changes when the controller adds support for SGLs (next patch), so add that check. Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 36ec8cbb1168..6ef4dc762b80 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -143,7 +143,12 @@ static inline void *nvme_addr_to_cmb(NvmeCtrl *n, hwaddr addr) static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) { - if (n->bar.cmbsz && nvme_addr_is_cmb(n, addr)) { + hwaddr hi = addr + size - 1; + if (hi < addr) { + return 1; + } + + if (n->bar.cmbsz && nvme_addr_is_cmb(n, addr) && nvme_addr_is_cmb(n, hi)) { memcpy(buf, nvme_addr_to_cmb(n, addr), size); return 0; } From patchwork Fri Sep 4 14:19:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274495 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 6D69FC43461 for ; Fri, 4 Sep 2020 14:27:02 +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 1C48C206B7 for ; Fri, 4 Sep 2020 14:27:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="KJLhalZL" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1C48C206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:58346 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECg9-0007SA-5n for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:27:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32860) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaS-0003cy-FW; Fri, 04 Sep 2020 10:21:08 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48024) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaK-0002jL-T0; Fri, 04 Sep 2020 10:21:08 -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 80379BFB13; Fri, 4 Sep 2020 14:20:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229235; bh=qPjW4FD7CdvD9XvY1Nzr37axoafPVoF8i8DNoAfghH0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KJLhalZL7/evqDFcqEGFwCjXJnmx2u9gcC/DE8m+ys1zoEoGa62iyLqJyhnTUzB24 mrBFBix1YfEMquW7tCZI5ml0ofaWd9+9NTbh8LIlxSV4B4Ql76YM3GNXg4pxTy6ARj F5L4mItQSmkLiKE9q4jTRwXtx3mFOx9zxEmU+LHPw6B32Jr2ReYE3gRLOhJ5fVW7hw /R9biUnwarnF8PMWYwzXx0sFy9hAfxdCxqiIDAgHybw50LeGR+BYDf9AjP5ImNp5pj B6sk0P4cUj9ZQie96oKIz040k5ZQRZOUV8td1xQtvCdnrrdsBcCEH8qThdIgmZp1uo iRdBOiKd/nPNQ== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 12/17] hw/block/nvme: add support for scatter gather lists Date: Fri, 4 Sep 2020 16:19:51 +0200 Message-Id: <20200904141956.576630-13-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen For now, support the Data Block, Segment and Last Segment descriptor types. See NVM Express 1.3d, Section 4.4 ("Scatter Gather List (SGL)"). Signed-off-by: Klaus Jensen Signed-off-by: Klaus Jensen Acked-by: Keith Busch --- hw/block/nvme.c | 329 ++++++++++++++++++++++++++++++++++-------- hw/block/trace-events | 4 + include/block/nvme.h | 6 +- 3 files changed, 279 insertions(+), 60 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 6ef4dc762b80..9bdcfeb901d9 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -414,13 +414,262 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2, return NVME_SUCCESS; } -static uint16_t nvme_dma_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, - uint64_t prp1, uint64_t prp2, DMADirection dir, +/* + * Map 'nsgld' data descriptors from 'segment'. The function will subtract the + * number of bytes mapped in len. + */ +static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg, + QEMUIOVector *iov, + NvmeSglDescriptor *segment, uint64_t nsgld, + size_t *len, NvmeRequest *req) +{ + dma_addr_t addr, trans_len; + uint32_t dlen; + uint16_t status; + + for (int i = 0; i < nsgld; i++) { + uint8_t type = NVME_SGL_TYPE(segment[i].type); + + switch (type) { + case NVME_SGL_DESCR_TYPE_DATA_BLOCK: + break; + case NVME_SGL_DESCR_TYPE_SEGMENT: + case NVME_SGL_DESCR_TYPE_LAST_SEGMENT: + return NVME_INVALID_NUM_SGL_DESCRS | NVME_DNR; + default: + return NVME_SGL_DESCR_TYPE_INVALID | NVME_DNR; + } + + dlen = le32_to_cpu(segment[i].len); + if (!dlen) { + continue; + } + + if (*len == 0) { + /* + * All data has been mapped, but the SGL contains additional + * segments and/or descriptors. The controller might accept + * ignoring the rest of the SGL. + */ + uint16_t sgls = le16_to_cpu(n->id_ctrl.sgls); + if (sgls & NVME_CTRL_SGLS_EXCESS_LENGTH) { + break; + } + + trace_pci_nvme_err_invalid_sgl_excess_length(nvme_cid(req)); + return NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + } + + trans_len = MIN(*len, dlen); + addr = le64_to_cpu(segment[i].addr); + + if (UINT64_MAX - addr < dlen) { + return NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + } + + status = nvme_map_addr(n, qsg, iov, addr, trans_len); + if (status) { + return status; + } + + *len -= trans_len; + } + + return NVME_SUCCESS; +} + +static uint16_t nvme_map_sgl(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov, + NvmeSglDescriptor sgl, size_t len, NvmeRequest *req) +{ + /* + * Read the segment in chunks of 256 descriptors (one 4k page) to avoid + * dynamically allocating a potentially huge SGL. The spec allows the SGL + * to be larger (as in number of bytes required to describe the SGL + * descriptors and segment chain) than the command transfer size, so it is + * not bounded by MDTS. + */ + const int SEG_CHUNK_SIZE = 256; + + NvmeSglDescriptor segment[SEG_CHUNK_SIZE], *sgld, *last_sgld; + uint64_t nsgld; + uint32_t seg_len; + uint16_t status; + bool sgl_in_cmb = false; + hwaddr addr; + int ret; + + sgld = &sgl; + addr = le64_to_cpu(sgl.addr); + + trace_pci_nvme_map_sgl(nvme_cid(req), NVME_SGL_TYPE(sgl.type), len); + + /* + * If the entire transfer can be described with a single data block it can + * be mapped directly. + */ + if (NVME_SGL_TYPE(sgl.type) == NVME_SGL_DESCR_TYPE_DATA_BLOCK) { + status = nvme_map_sgl_data(n, qsg, iov, sgld, 1, &len, req); + if (status) { + goto unmap; + } + + goto out; + } + + /* + * If the segment is located in the CMB, the submission queue of the + * request must also reside there. + */ + if (nvme_addr_is_cmb(n, addr)) { + if (!nvme_addr_is_cmb(n, req->sq->dma_addr)) { + return NVME_INVALID_USE_OF_CMB | NVME_DNR; + } + + sgl_in_cmb = true; + } + + for (;;) { + switch (NVME_SGL_TYPE(sgld->type)) { + case NVME_SGL_DESCR_TYPE_SEGMENT: + case NVME_SGL_DESCR_TYPE_LAST_SEGMENT: + break; + default: + return NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; + } + + seg_len = le32_to_cpu(sgld->len); + + /* check the length of the (Last) Segment descriptor */ + if (!seg_len || seg_len & 0xf) { + return NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; + } + + if (UINT64_MAX - addr < seg_len) { + return NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + } + + nsgld = seg_len / sizeof(NvmeSglDescriptor); + + while (nsgld > SEG_CHUNK_SIZE) { + if (nvme_addr_read(n, addr, segment, sizeof(segment))) { + trace_pci_nvme_err_addr_read(addr); + status = NVME_DATA_TRANSFER_ERROR; + goto unmap; + } + + status = nvme_map_sgl_data(n, qsg, iov, segment, SEG_CHUNK_SIZE, + &len, req); + if (status) { + goto unmap; + } + + nsgld -= SEG_CHUNK_SIZE; + addr += SEG_CHUNK_SIZE * sizeof(NvmeSglDescriptor); + } + + ret = nvme_addr_read(n, addr, segment, nsgld * + sizeof(NvmeSglDescriptor)); + if (ret) { + trace_pci_nvme_err_addr_read(addr); + status = NVME_DATA_TRANSFER_ERROR; + goto unmap; + } + + last_sgld = &segment[nsgld - 1]; + + /* if the segment ends with a Data Block, then we are done */ + if (NVME_SGL_TYPE(last_sgld->type) == NVME_SGL_DESCR_TYPE_DATA_BLOCK) { + status = nvme_map_sgl_data(n, qsg, iov, segment, nsgld, &len, req); + if (status) { + goto unmap; + } + + goto out; + } + + /* + * If the last descriptor was not a Data Block, then the current + * segment must not be a Last Segment. + */ + if (NVME_SGL_TYPE(sgld->type) == NVME_SGL_DESCR_TYPE_LAST_SEGMENT) { + status = NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; + goto unmap; + } + + sgld = last_sgld; + addr = le64_to_cpu(sgld->addr); + + /* + * Do not map the last descriptor; it will be a Segment or Last Segment + * descriptor and is handled by the next iteration. + */ + status = nvme_map_sgl_data(n, qsg, iov, segment, nsgld - 1, &len, req); + if (status) { + goto unmap; + } + + /* + * If the next segment is in the CMB, make sure that the sgl was + * already located there. + */ + if (sgl_in_cmb != nvme_addr_is_cmb(n, addr)) { + status = NVME_INVALID_USE_OF_CMB | NVME_DNR; + goto unmap; + } + } + +out: + /* if there is any residual left in len, the SGL was too short */ + if (len) { + status = NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + goto unmap; + } + + return NVME_SUCCESS; + +unmap: + if (iov->iov) { + qemu_iovec_destroy(iov); + } + + if (qsg->sg) { + qemu_sglist_destroy(qsg); + } + + return status; +} + +static uint16_t nvme_map_dptr(NvmeCtrl *n, size_t len, NvmeRequest *req) +{ + uint64_t prp1, prp2; + + switch (NVME_CMD_FLAGS_PSDT(req->cmd.flags)) { + case NVME_PSDT_PRP: + prp1 = le64_to_cpu(req->cmd.dptr.prp1); + prp2 = le64_to_cpu(req->cmd.dptr.prp2); + + return nvme_map_prp(n, prp1, prp2, len, req); + case NVME_PSDT_SGL_MPTR_CONTIGUOUS: + case NVME_PSDT_SGL_MPTR_SGL: + /* SGLs shall not be used for Admin commands in NVMe over PCIe */ + if (!req->sq->sqid) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + return nvme_map_sgl(n, &req->qsg, &req->iov, req->cmd.dptr.sgl, len, + req); + default: + return NVME_INVALID_FIELD; + } +} + +static uint16_t nvme_dma(NvmeCtrl *n, uint8_t *ptr, uint32_t len, + DMADirection dir, NvmeRequest *req) { uint16_t status = NVME_SUCCESS; - status = nvme_map_prp(n, prp1, prp2, len, req); + status = nvme_map_dptr(n, len, req); if (status) { return status; } @@ -459,15 +708,6 @@ static uint16_t nvme_dma_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, return status; } -static uint16_t nvme_map_dptr(NvmeCtrl *n, size_t len, NvmeRequest *req) -{ - NvmeCmd *cmd = &req->cmd; - uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); - uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); - - return nvme_map_prp(n, prp1, prp2, len, req); -} - static void nvme_post_cqes(void *opaque) { NvmeCQueue *cq = opaque; @@ -994,10 +1234,7 @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, uint64_t off, NvmeRequest *req) { - NvmeCmd *cmd = &req->cmd; - uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); - uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); - uint32_t nsid = le32_to_cpu(cmd->nsid); + uint32_t nsid = le32_to_cpu(req->cmd.nsid); uint32_t trans_len; time_t current_ms; @@ -1046,17 +1283,14 @@ static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, nvme_clear_events(n, NVME_AER_TYPE_SMART); } - return nvme_dma_prp(n, (uint8_t *) &smart + off, trans_len, prp1, prp2, - DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, (uint8_t *) &smart + off, trans_len, + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_fw_log_info(NvmeCtrl *n, uint32_t buf_len, uint64_t off, NvmeRequest *req) { uint32_t trans_len; - NvmeCmd *cmd = &req->cmd; - uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); - uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); NvmeFwSlotInfoLog fw_log = { .afi = 0x1, }; @@ -1069,17 +1303,14 @@ static uint16_t nvme_fw_log_info(NvmeCtrl *n, uint32_t buf_len, uint64_t off, trans_len = MIN(sizeof(fw_log) - off, buf_len); - return nvme_dma_prp(n, (uint8_t *) &fw_log + off, trans_len, prp1, prp2, - DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, (uint8_t *) &fw_log + off, trans_len, + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_error_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, uint64_t off, NvmeRequest *req) { uint32_t trans_len; - NvmeCmd *cmd = &req->cmd; - uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); - uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); NvmeErrorLog errlog; if (!rae) { @@ -1094,8 +1325,8 @@ static uint16_t nvme_error_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, trans_len = MIN(sizeof(errlog) - off, buf_len); - return nvme_dma_prp(n, (uint8_t *)&errlog, trans_len, prp1, prp2, - DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, (uint8_t *)&errlog, trans_len, + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req) @@ -1255,14 +1486,10 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeRequest *req) { - NvmeIdentify *c = (NvmeIdentify *)&req->cmd; - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); - trace_pci_nvme_identify_ctrl(); - return nvme_dma_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl), prp1, - prp2, DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl), + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req) @@ -1270,8 +1497,6 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req) NvmeNamespace *ns; NvmeIdentify *c = (NvmeIdentify *)&req->cmd; uint32_t nsid = le32_to_cpu(c->nsid); - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); trace_pci_nvme_identify_ns(nsid); @@ -1282,8 +1507,8 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req) ns = &n->namespaces[nsid - 1]; - return nvme_dma_prp(n, (uint8_t *)&ns->id_ns, sizeof(ns->id_ns), prp1, - prp2, DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, (uint8_t *)&ns->id_ns, sizeof(ns->id_ns), + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) @@ -1291,8 +1516,6 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) NvmeIdentify *c = (NvmeIdentify *)&req->cmd; static const int data_len = NVME_IDENTIFY_DATA_SIZE; uint32_t min_nsid = le32_to_cpu(c->nsid); - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); uint32_t *list; uint16_t ret; int i, j = 0; @@ -1319,8 +1542,8 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) break; } } - ret = nvme_dma_prp(n, (uint8_t *)list, data_len, prp1, prp2, - DMA_DIRECTION_FROM_DEVICE, req); + ret = nvme_dma(n, (uint8_t *)list, data_len, DMA_DIRECTION_FROM_DEVICE, + req); g_free(list); return ret; } @@ -1329,8 +1552,6 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) { NvmeIdentify *c = (NvmeIdentify *)&req->cmd; uint32_t nsid = le32_to_cpu(c->nsid); - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); uint8_t list[NVME_IDENTIFY_DATA_SIZE]; @@ -1362,8 +1583,8 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) ns_descrs->uuid.hdr.nidl = NVME_NIDT_UUID_LEN; stl_be_p(&ns_descrs->uuid.v, nsid); - return nvme_dma_prp(n, list, NVME_IDENTIFY_DATA_SIZE, prp1, prp2, - DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, list, NVME_IDENTIFY_DATA_SIZE, + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req) @@ -1439,14 +1660,10 @@ static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n) static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) { - NvmeCmd *cmd = &req->cmd; - 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); - return nvme_dma_prp(n, (uint8_t *)×tamp, sizeof(timestamp), prp1, - prp2, DMA_DIRECTION_FROM_DEVICE, req); + return nvme_dma(n, (uint8_t *)×tamp, sizeof(timestamp), + DMA_DIRECTION_FROM_DEVICE, req); } static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) @@ -1575,12 +1792,9 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) { uint16_t ret; uint64_t timestamp; - NvmeCmd *cmd = &req->cmd; - uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1); - uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2); - ret = nvme_dma_prp(n, (uint8_t *)×tamp, sizeof(timestamp), prp1, - prp2, DMA_DIRECTION_TO_DEVICE, req); + ret = nvme_dma(n, (uint8_t *)×tamp, sizeof(timestamp), + DMA_DIRECTION_TO_DEVICE, req); if (ret != NVME_SUCCESS) { return ret; } @@ -2507,6 +2721,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->nn = cpu_to_le32(n->num_namespaces); id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROES | NVME_ONCS_TIMESTAMP | NVME_ONCS_FEATURES); + id->sgls = cpu_to_le32(NVME_CTRL_SGLS_SUPPORT_NO_ALIGN); subnqn = g_strdup_printf("nqn.2019-08.org.qemu:%s", n->params.serial); strpadcpy((char *)id->subnqn, sizeof(id->subnqn), subnqn, '\0'); diff --git a/hw/block/trace-events b/hw/block/trace-events index fb3bf1be5e07..7fe119bd625c 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -36,6 +36,7 @@ pci_nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2 pci_nvme_map_addr(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64"" pci_nvme_map_addr_cmb(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64"" pci_nvme_map_prp(uint64_t trans_len, uint32_t len, uint64_t prp1, uint64_t prp2, int num_prps) "trans_len %"PRIu64" len %"PRIu32" prp1 0x%"PRIx64" prp2 0x%"PRIx64" num_prps %d" +pci_nvme_map_sgl(uint16_t cid, uint8_t typ, uint64_t len) "cid %"PRIu16" type 0x%"PRIx8" len %"PRIu64"" pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" pci_nvme_rw(uint16_t cid, const char *verb, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" \"%s\" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64"" @@ -91,6 +92,9 @@ pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu" pci_nvme_err_addr_read(uint64_t addr) "addr 0x%"PRIx64"" pci_nvme_err_addr_write(uint64_t addr) "addr 0x%"PRIx64"" pci_nvme_err_aio(uint16_t cid, void *aio, const char *blkname, uint64_t offset, const char *opc, void *req, uint16_t status) "cid %"PRIu16" aio %p blk \"%s\" offset %"PRIu64" opc \"%s\" req %p status 0x%"PRIx16"" +pci_nvme_err_invalid_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type 0x%"PRIx8"" +pci_nvme_err_invalid_num_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type 0x%"PRIx8"" +pci_nvme_err_invalid_sgl_excess_length(uint16_t cid) "cid %"PRIu16"" pci_nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size" pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or not page aligned: 0x%"PRIx64"" pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64"" diff --git a/include/block/nvme.h b/include/block/nvme.h index c8d0a3473f0d..7eba658073f5 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -412,9 +412,9 @@ typedef union NvmeCmdDptr { } NvmeCmdDptr; enum NvmePsdt { - PSDT_PRP = 0x0, - PSDT_SGL_MPTR_CONTIGUOUS = 0x1, - PSDT_SGL_MPTR_SGL = 0x2, + NVME_PSDT_PRP = 0x0, + NVME_PSDT_SGL_MPTR_CONTIGUOUS = 0x1, + NVME_PSDT_SGL_MPTR_SGL = 0x2, }; typedef struct QEMU_PACKED NvmeCmd { From patchwork Fri Sep 4 14:19:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274494 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 91285C433E2 for ; Fri, 4 Sep 2020 14:28:54 +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 4A1D6206B8 for ; Fri, 4 Sep 2020 14:28:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="fse/9A+x" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4A1D6206B8 Authentication-Results: mail.kernel.org; dmarc=fail (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]:37372 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kEChx-0001z6-D3 for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:28:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32832) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaO-0003RQ-AB; Fri, 04 Sep 2020 10:21:04 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48030) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaL-0002jo-Jw; Fri, 04 Sep 2020 10:21:03 -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 E5B1CBFB14; Fri, 4 Sep 2020 14:20:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229236; bh=ULU7lIQRoJxUpQ9KR9VWBQNkz+YpY+nCXiz6yhnMBlE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fse/9A+x4vXrp9NLBj1ILzNtSI0I09r2RuXlGZ6WTVZ5+lQaKHxtYmjw7l0N6v21Y zL8TKvw3g2lGmR9ZmcQ6o8k9ssQBQ4TKPNAqnEn/OwtMZiAx40/t503ZtlPOoTGc+4 /71JHWBgiDTSfYSw52K3bh4mDYAygDwBwl8REVTK42HoUGsIGJH+rMEw4ddh8FcUMt HKBM+wmxQ/9k+StUlFdZkkr0z8HLzTNS+oAH2By/2KV8lq7QHS+mFuXDiB32+101Vm pSMFNo9uCTn8oXdtIDb0aeH/9BVtE5gqjWLsQXNiT1Kbko4tgULpWmOtSACQAbQtyb Oc1agnwAfKgmQ== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 13/17] hw/block/nvme: add support for sgl bit bucket descriptor Date: Fri, 4 Sep 2020 16:19:52 +0200 Message-Id: <20200904141956.576630-14-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Gollu Appalanaidu , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Gollu Appalanaidu This adds support for SGL descriptor type 0x1 (bit bucket descriptor). See the NVM Express v1.3d specification, Section 4.4 ("Scatter Gather List (SGL)"). Signed-off-by: Gollu Appalanaidu Signed-off-by: Klaus Jensen --- hw/block/nvme.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 9bdcfeb901d9..6340af226341 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -431,6 +431,10 @@ static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg, uint8_t type = NVME_SGL_TYPE(segment[i].type); switch (type) { + case NVME_SGL_DESCR_TYPE_BIT_BUCKET: + if (req->cmd.opcode == NVME_CMD_WRITE) { + continue; + } case NVME_SGL_DESCR_TYPE_DATA_BLOCK: break; case NVME_SGL_DESCR_TYPE_SEGMENT: @@ -441,6 +445,7 @@ static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg, } dlen = le32_to_cpu(segment[i].len); + if (!dlen) { continue; } @@ -461,6 +466,11 @@ static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg, } trans_len = MIN(*len, dlen); + + if (type == NVME_SGL_DESCR_TYPE_BIT_BUCKET) { + goto next; + } + addr = le64_to_cpu(segment[i].addr); if (UINT64_MAX - addr < dlen) { @@ -472,6 +482,7 @@ static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg, return status; } +next: *len -= trans_len; } @@ -541,7 +552,8 @@ static uint16_t nvme_map_sgl(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov, seg_len = le32_to_cpu(sgld->len); /* check the length of the (Last) Segment descriptor */ - if (!seg_len || seg_len & 0xf) { + if ((!seg_len || seg_len & 0xf) && + (NVME_SGL_TYPE(sgld->type) != NVME_SGL_DESCR_TYPE_BIT_BUCKET)) { return NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; } @@ -578,19 +590,27 @@ static uint16_t nvme_map_sgl(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov, last_sgld = &segment[nsgld - 1]; - /* if the segment ends with a Data Block, then we are done */ - if (NVME_SGL_TYPE(last_sgld->type) == NVME_SGL_DESCR_TYPE_DATA_BLOCK) { + /* + * If the segment ends with a Data Block or Bit Bucket Descriptor Type, + * then we are done. + */ + switch (NVME_SGL_TYPE(last_sgld->type)) { + case NVME_SGL_DESCR_TYPE_DATA_BLOCK: + case NVME_SGL_DESCR_TYPE_BIT_BUCKET: status = nvme_map_sgl_data(n, qsg, iov, segment, nsgld, &len, req); if (status) { goto unmap; } goto out; + + default: + break; } /* - * If the last descriptor was not a Data Block, then the current - * segment must not be a Last Segment. + * If the last descriptor was not a Data Block or Bit Bucket, then the + * current segment must not be a Last Segment. */ if (NVME_SGL_TYPE(sgld->type) == NVME_SGL_DESCR_TYPE_LAST_SEGMENT) { status = NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; @@ -2721,7 +2741,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->nn = cpu_to_le32(n->num_namespaces); id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROES | NVME_ONCS_TIMESTAMP | NVME_ONCS_FEATURES); - id->sgls = cpu_to_le32(NVME_CTRL_SGLS_SUPPORT_NO_ALIGN); + id->sgls = cpu_to_le32(NVME_CTRL_SGLS_SUPPORT_NO_ALIGN | + NVME_CTRL_SGLS_BITBUCKET); subnqn = g_strdup_printf("nqn.2019-08.org.qemu:%s", n->params.serial); strpadcpy((char *)id->subnqn, sizeof(id->subnqn), subnqn, '\0'); From patchwork Fri Sep 4 14:19:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 306165 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 B7A54C433E2 for ; Fri, 4 Sep 2020 14:23:36 +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 78A182074D for ; Fri, 4 Sep 2020 14:23:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="YOpt66dr" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 78A182074D Authentication-Results: mail.kernel.org; dmarc=fail (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]:41468 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECcp-0000Fl-LV for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:23:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32840) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaO-0003SM-Mw; Fri, 04 Sep 2020 10:21:04 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48028) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaL-0002jh-FE; Fri, 04 Sep 2020 10:21:04 -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 4FE7FBFB54; Fri, 4 Sep 2020 14:20:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229236; bh=S0gbzHUcsCyIvbaedPZcFblTZFt6MpvV2k1wK6JvNRQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YOpt66dr4Y3myH2wWOtO9/qJFBUkAjlpRuqPNVsoEcQFPXyGVHNMouHpeqr+Yz3bG 3E/ZvV7uX/Ys6V26m9KicXjxSB0qMpbZOqs2Ii08MWIoGhrti6onlV9QIB/RFcntO/ eMoLplY5nF5a+MxdpHfeDyQokcViGNrDpYxAR7S7D71DfMWVc0CQihEkw5Z3a2+lRo LKV7107wveaOBMVbZvGJQ2UO7fhl7kE2PppL8k1BWrbqrb7SYIjs5JL8p2dqiiGgMD n5gWCfMqRAYlGfza8fFWHX1uJmun9S6D4Rh5HdTT5X3Ko8AN8gLgJsNxxiVFnRFEuv RI8f0BI7A0NPg== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 14/17] hw/block/nvme: refactor identify active namespace id list Date: Fri, 4 Sep 2020 16:19:53 +0200 Message-Id: <20200904141956.576630-15-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen , Maxim Levitsky Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Prepare to support inactive namespaces. Signed-off-by: Klaus Jensen Reviewed-by: Maxim Levitsky --- hw/block/nvme.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 6340af226341..4155cb797856 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -1538,7 +1538,7 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) uint32_t min_nsid = le32_to_cpu(c->nsid); uint32_t *list; uint16_t ret; - int i, j = 0; + int j = 0; trace_pci_nvme_identify_nslist(min_nsid); @@ -1553,11 +1553,11 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) } list = g_malloc0(data_len); - for (i = 0; i < n->num_namespaces; i++) { - if (i < min_nsid) { + for (int i = 1; i <= n->num_namespaces; i++) { + if (i <= min_nsid) { continue; } - list[j++] = cpu_to_le32(i + 1); + list[j++] = cpu_to_le32(i); if (j == data_len / sizeof(uint32_t)) { break; } From patchwork Fri Sep 4 14:19:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 306160 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 0E592C433E2 for ; Fri, 4 Sep 2020 14:30:11 +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 B3913206B7 for ; Fri, 4 Sep 2020 14:30:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="j0dTBGKc" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B3913206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:43856 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECjB-0004h0-Rr for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:30:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32858) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaR-0003a1-DC; Fri, 04 Sep 2020 10:21:07 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48032) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaL-0002k0-Sf; Fri, 04 Sep 2020 10:21:07 -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 CA35BBFB56; Fri, 4 Sep 2020 14:20:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229237; bh=z4GSixwdPOoeLDm8TtHSRwK16l/0rG3XfXnca0iJlak=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j0dTBGKc4yTVSZ4jdHRDsJBMcnia5jt5JSjZrWSAjtZnpdS/5BAtmRR3C7x9hgw0/ En7PToQsjxT7uuGrSGZ55Ds6wO1FztfJu34Q2SPyQuSZNFsvPO2lfmHtols3+SwOwG TzFGmQFePYl/XcdcWbtW1IYnZPThG3zXyjfqrp9ux+wRCtN836IaL3NibsykkO5o/i +/bS0ilF2JDYjSalAucTRBd0n8mQXNBJ79ojDNVXUyMtY1AhAs0brOHonOcY8Pdk1V jr0ZMsCuPVFW1rmSp8Ejm3PBHri78UrnWpfr45mSKDayxS7unGTZ3X0YWgjGtw1Rmr DuEwFMEAd8Krw== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 15/17] hw/block/nvme: support multiple namespaces Date: Fri, 4 Sep 2020 16:19:54 +0200 Message-Id: <20200904141956.576630-16-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Minwoo Im , Klaus Jensen , Klaus Jensen Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen This adds support for multiple namespaces by introducing a new 'nvme-ns' device model. The nvme device creates a bus named from the device name ('id'). The nvme-ns devices then connect to this and registers themselves with the nvme device. This changes how an nvme device is created. Example with two namespaces: -drive file=nvme0n1.img,if=none,id=disk1 -drive file=nvme0n2.img,if=none,id=disk2 -device nvme,serial=deadbeef,id=nvme0 -device nvme-ns,drive=disk1,bus=nvme0,nsid=1 -device nvme-ns,drive=disk2,bus=nvme0,nsid=2 The drive property is kept on the nvme device to keep the change backward compatible, but the property is now optional. Specifying a drive for the nvme device will always create the namespace with nsid 1. Signed-off-by: Klaus Jensen Signed-off-by: Klaus Jensen Reviewed-by: Keith Busch Reviewed-by: Minwoo Im --- hw/block/meson.build | 2 +- hw/block/nvme-ns.c | 185 +++++++++++++++++++++++++++++++ hw/block/nvme-ns.h | 74 +++++++++++++ hw/block/nvme.c | 247 +++++++++++++++++++++++++++--------------- hw/block/nvme.h | 46 ++++---- hw/block/trace-events | 8 +- 6 files changed, 447 insertions(+), 115 deletions(-) create mode 100644 hw/block/nvme-ns.c create mode 100644 hw/block/nvme-ns.h diff --git a/hw/block/meson.build b/hw/block/meson.build index 78cad8f7cba1..602ca6c8541d 100644 --- a/hw/block/meson.build +++ b/hw/block/meson.build @@ -13,7 +13,7 @@ softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c')) softmmu_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c')) softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c')) softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('tc58128.c')) -softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('nvme.c')) +softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('nvme.c', 'nvme-ns.c')) specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c')) specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c')) diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c new file mode 100644 index 000000000000..0d65b0998617 --- /dev/null +++ b/hw/block/nvme-ns.c @@ -0,0 +1,185 @@ +/* + * QEMU NVM Express Virtual Namespace + * + * Copyright (c) 2019 CNEX Labs + * Copyright (c) 2020 Samsung Electronics + * + * Authors: + * Klaus Jensen + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "qemu/log.h" +#include "hw/block/block.h" +#include "hw/pci/pci.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" +#include "qapi/error.h" + +#include "hw/qdev-properties.h" +#include "hw/qdev-core.h" + +#include "nvme.h" +#include "nvme-ns.h" + +static void nvme_ns_init(NvmeNamespace *ns) +{ + NvmeIdNs *id_ns = &ns->id_ns; + + if (blk_get_flags(ns->blk) & BDRV_O_UNMAP) { + ns->id_ns.dlfeat = 0x9; + } + + id_ns->lbaf[0].ds = BDRV_SECTOR_BITS; + + id_ns->nsze = cpu_to_le64(nvme_ns_nlbas(ns)); + + /* no thin provisioning */ + id_ns->ncap = id_ns->nsze; + id_ns->nuse = id_ns->ncap; +} + +static int nvme_ns_init_blk(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) +{ + uint64_t perm, shared_perm; + + Error *local_err = NULL; + int ret; + + perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE; + shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | + BLK_PERM_GRAPH_MOD; + + ret = blk_set_perm(ns->blk, perm, shared_perm, &local_err); + if (ret) { + error_propagate_prepend(errp, local_err, + "could not set block permissions: "); + return ret; + } + + ns->size = blk_getlength(ns->blk); + if (ns->size < 0) { + error_setg_errno(errp, -ns->size, "could not get blockdev size"); + return -1; + } + + switch (n->conf.wce) { + case ON_OFF_AUTO_ON: + n->features.vwc = 1; + break; + case ON_OFF_AUTO_OFF: + n->features.vwc = 0; + break; + case ON_OFF_AUTO_AUTO: + n->features.vwc = blk_enable_write_cache(ns->blk); + break; + default: + abort(); + } + + blk_set_enable_write_cache(ns->blk, n->features.vwc); + + return 0; +} + +static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp) +{ + if (!ns->blk) { + error_setg(errp, "block backend not configured"); + return -1; + } + + return 0; +} + +int nvme_ns_setup(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) +{ + if (nvme_ns_check_constraints(ns, errp)) { + return -1; + } + + if (nvme_ns_init_blk(n, ns, errp)) { + return -1; + } + + nvme_ns_init(ns); + if (nvme_register_namespace(n, ns, errp)) { + return -1; + } + + return 0; +} + +void nvme_ns_drain(NvmeNamespace *ns) +{ + blk_drain(ns->blk); +} + +void nvme_ns_flush(NvmeNamespace *ns) +{ + blk_flush(ns->blk); +} + +static void nvme_ns_realize(DeviceState *dev, Error **errp) +{ + NvmeNamespace *ns = NVME_NS(dev); + BusState *s = qdev_get_parent_bus(dev); + NvmeCtrl *n = NVME(s->parent); + Error *local_err = NULL; + + if (nvme_ns_setup(n, ns, &local_err)) { + error_propagate_prepend(errp, local_err, + "could not setup namespace: "); + return; + } +} + +static Property nvme_ns_props[] = { + DEFINE_PROP_DRIVE("drive", NvmeNamespace, blk), + DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void nvme_ns_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + + dc->bus_type = TYPE_NVME_BUS; + dc->realize = nvme_ns_realize; + device_class_set_props(dc, nvme_ns_props); + dc->desc = "Virtual NVMe namespace"; +} + +static void nvme_ns_instance_init(Object *obj) +{ + NvmeNamespace *ns = NVME_NS(obj); + char *bootindex = g_strdup_printf("/namespace@%d,0", ns->params.nsid); + + device_add_bootindex_property(obj, &ns->bootindex, "bootindex", + bootindex, DEVICE(obj)); + + g_free(bootindex); +} + +static const TypeInfo nvme_ns_info = { + .name = TYPE_NVME_NS, + .parent = TYPE_DEVICE, + .class_init = nvme_ns_class_init, + .instance_size = sizeof(NvmeNamespace), + .instance_init = nvme_ns_instance_init, +}; + +static void nvme_ns_register_types(void) +{ + type_register_static(&nvme_ns_info); +} + +type_init(nvme_ns_register_types) diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h new file mode 100644 index 000000000000..4659e566f443 --- /dev/null +++ b/hw/block/nvme-ns.h @@ -0,0 +1,74 @@ +/* + * QEMU NVM Express Virtual Namespace + * + * Copyright (c) 2019 CNEX Labs + * Copyright (c) 2020 Samsung Electronics + * + * Authors: + * Klaus Jensen + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + * + */ + +#ifndef NVME_NS_H +#define NVME_NS_H + +#define TYPE_NVME_NS "nvme-ns" +#define NVME_NS(obj) \ + OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) + +typedef struct NvmeNamespaceParams { + uint32_t nsid; +} NvmeNamespaceParams; + +typedef struct NvmeNamespace { + DeviceState parent_obj; + BlockBackend *blk; + int32_t bootindex; + int64_t size; + NvmeIdNs id_ns; + + NvmeNamespaceParams params; +} NvmeNamespace; + +static inline uint32_t nvme_nsid(NvmeNamespace *ns) +{ + if (ns) { + return ns->params.nsid; + } + + return -1; +} + +static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns) +{ + NvmeIdNs *id_ns = &ns->id_ns; + return &id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; +} + +static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns) +{ + return nvme_ns_lbaf(ns)->ds; +} + +/* calculate the number of LBAs that the namespace can accomodate */ +static inline uint64_t nvme_ns_nlbas(NvmeNamespace *ns) +{ + return ns->size >> nvme_ns_lbads(ns); +} + +/* convert an LBA to the equivalent in bytes */ +static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) +{ + return lba << nvme_ns_lbads(ns); +} + +typedef struct NvmeCtrl NvmeCtrl; + +int nvme_ns_setup(NvmeCtrl *n, NvmeNamespace *ns, Error **errp); +void nvme_ns_drain(NvmeNamespace *ns); +void nvme_ns_flush(NvmeNamespace *ns); + +#endif /* NVME_NS_H */ diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 4155cb797856..453d3a89d475 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -17,12 +17,13 @@ /** * Usage: add options: * -drive file=,if=none,id= - * -device nvme,drive=,serial=,id=, \ + * -device nvme,serial=,id=, \ * cmb_size_mb=, \ * [pmrdev=,] \ * max_ioqpairs=, \ * aerl=, aer_max_queued=, \ * mdts= + * -device nvme-ns,drive=,bus=bus_name,nsid= * * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at * offset 0 in BAR2 and supports only WDS, RDS and SQS for now. @@ -69,6 +70,7 @@ #include "qemu/cutils.h" #include "trace.h" #include "nvme.h" +#include "nvme-ns.h" #define NVME_MAX_IOQPAIRS 0xffff #define NVME_DB_SIZE 4 @@ -156,6 +158,11 @@ static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) return pci_dma_read(&n->parent_obj, addr, buf, size); } +static bool nvme_nsid_valid(NvmeCtrl *n, uint32_t nsid) +{ + return nsid && (nsid == NVME_NSID_BROADCAST || nsid <= n->num_namespaces); +} + static int nvme_check_sqid(NvmeCtrl *n, uint16_t sqid) { return sqid < n->params.max_ioqpairs + 1 && n->sq[sqid] != NULL ? 0 : -1; @@ -1023,7 +1030,9 @@ static void nvme_aio_cb(void *opaque, int ret) static uint16_t nvme_flush(NvmeCtrl *n, NvmeRequest *req) { - return nvme_aio_add(req, nvme_aio_new(NVME_AIO_OPC_FLUSH, n->conf.blk, 0)); + NvmeNamespace *ns = req->ns; + + return nvme_aio_add(req, nvme_aio_new(NVME_AIO_OPC_FLUSH, ns->blk, 0)); } static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) @@ -1037,7 +1046,7 @@ static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) uint32_t count = nvme_l2b(ns, nlb); uint16_t status; - trace_pci_nvme_write_zeroes(nvme_cid(req), slba, nlb); + trace_pci_nvme_write_zeroes(nvme_cid(req), nvme_nsid(ns), slba, nlb); status = nvme_check_bounds(n, ns, slba, nlb); if (status) { @@ -1045,7 +1054,7 @@ static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) return status; } - aio = nvme_aio_new(NVME_AIO_OPC_WRITE_ZEROES, n->conf.blk, offset); + aio = nvme_aio_new(NVME_AIO_OPC_WRITE_ZEROES, ns->blk, offset); aio->len = count; return nvme_aio_add(req, aio); @@ -1064,8 +1073,8 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) bool is_write = nvme_req_is_write(req); uint16_t status; - trace_pci_nvme_rw(nvme_cid(req), nvme_io_opc_str(rw->opcode), nlb, - data_size, slba); + trace_pci_nvme_rw(nvme_cid(req), nvme_io_opc_str(rw->opcode), + nvme_nsid(ns), nlb, data_size, slba); status = nvme_check_mdts(n, data_size); if (status) { @@ -1085,7 +1094,7 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) } aio = nvme_aio_new(is_write ? NVME_AIO_OPC_WRITE : NVME_AIO_OPC_READ, - n->conf.blk, data_offset); + ns->blk, data_offset); if (req->qsg.sg) { aio->payload = &req->qsg; @@ -1099,7 +1108,7 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) return nvme_aio_add(req, aio); invalid: - block_acct_invalid(blk_get_stats(n->conf.blk), + block_acct_invalid(blk_get_stats(ns->blk), is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ); return status; } @@ -1111,12 +1120,15 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) trace_pci_nvme_io_cmd(nvme_cid(req), nsid, nvme_sqid(req), req->cmd.opcode, nvme_io_opc_str(req->cmd.opcode)); - if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { - trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces); + if (!nvme_nsid_valid(n, nsid)) { return NVME_INVALID_NSID | NVME_DNR; } - req->ns = &n->namespaces[nsid - 1]; + req->ns = nvme_ns(n, nsid); + if (unlikely(!req->ns)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + switch (req->cmd.opcode) { case NVME_CMD_FLUSH: return nvme_flush(n, req); @@ -1261,18 +1273,24 @@ static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, uint64_t units_read = 0, units_written = 0; uint64_t read_commands = 0, write_commands = 0; NvmeSmartLog smart; - BlockAcctStats *s; if (nsid && nsid != 0xffffffff) { return NVME_INVALID_FIELD | NVME_DNR; } - s = blk_get_stats(n->conf.blk); + for (int i = 1; i <= n->num_namespaces; i++) { + NvmeNamespace *ns = nvme_ns(n, i); + if (!ns) { + continue; + } - units_read = s->nr_bytes[BLOCK_ACCT_READ] >> BDRV_SECTOR_BITS; - units_written = s->nr_bytes[BLOCK_ACCT_WRITE] >> BDRV_SECTOR_BITS; - read_commands = s->nr_ops[BLOCK_ACCT_READ]; - write_commands = s->nr_ops[BLOCK_ACCT_WRITE]; + BlockAcctStats *s = blk_get_stats(ns->blk); + + units_read += s->nr_bytes[BLOCK_ACCT_READ] >> BDRV_SECTOR_BITS; + units_written += s->nr_bytes[BLOCK_ACCT_WRITE] >> BDRV_SECTOR_BITS; + read_commands += s->nr_ops[BLOCK_ACCT_READ]; + write_commands += s->nr_ops[BLOCK_ACCT_WRITE]; + } if (off > sizeof(smart)) { return NVME_INVALID_FIELD | NVME_DNR; @@ -1516,18 +1534,23 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req) { NvmeNamespace *ns; NvmeIdentify *c = (NvmeIdentify *)&req->cmd; + NvmeIdNs *id_ns, inactive = { 0 }; uint32_t nsid = le32_to_cpu(c->nsid); trace_pci_nvme_identify_ns(nsid); - if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { - trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces); + if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) { return NVME_INVALID_NSID | NVME_DNR; } - ns = &n->namespaces[nsid - 1]; + ns = nvme_ns(n, nsid); + if (unlikely(!ns)) { + id_ns = &inactive; + } else { + id_ns = &ns->id_ns; + } - return nvme_dma(n, (uint8_t *)&ns->id_ns, sizeof(ns->id_ns), + return nvme_dma(n, (uint8_t *)id_ns, sizeof(NvmeIdNs), DMA_DIRECTION_FROM_DEVICE, req); } @@ -1554,7 +1577,7 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) list = g_malloc0(data_len); for (int i = 1; i <= n->num_namespaces; i++) { - if (i <= min_nsid) { + if (i <= min_nsid || !nvme_ns(n, i)) { continue; } list[j++] = cpu_to_le32(i); @@ -1572,7 +1595,6 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) { NvmeIdentify *c = (NvmeIdentify *)&req->cmd; uint32_t nsid = le32_to_cpu(c->nsid); - uint8_t list[NVME_IDENTIFY_DATA_SIZE]; struct data { @@ -1586,11 +1608,14 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) trace_pci_nvme_identify_ns_descr_list(nsid); - if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { - trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces); + if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) { return NVME_INVALID_NSID | NVME_DNR; } + if (unlikely(!nvme_ns(n, nsid))) { + return NVME_INVALID_FIELD | NVME_DNR; + } + memset(list, 0x0, sizeof(list)); /* @@ -1708,7 +1733,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) } if (nvme_feature_cap[fid] & NVME_FEAT_CAP_NS) { - if (!nsid || nsid > n->num_namespaces) { + if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) { /* * The Reservation Notification Mask and Reservation Persistence * features require a status code of Invalid Field in Command when @@ -1718,6 +1743,10 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) */ return NVME_INVALID_NSID | NVME_DNR; } + + if (!nvme_ns(n, nsid)) { + return NVME_INVALID_FIELD | NVME_DNR; + } } switch (sel) { @@ -1755,7 +1784,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) return NVME_INVALID_FIELD | NVME_DNR; case NVME_VOLATILE_WRITE_CACHE: - result = blk_enable_write_cache(n->conf.blk); + result = n->features.vwc; trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); goto out; case NVME_ASYNCHRONOUS_EVENT_CONF: @@ -1826,6 +1855,8 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) { + NvmeNamespace *ns; + NvmeCmd *cmd = &req->cmd; uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint32_t dw11 = le32_to_cpu(cmd->cdw11); @@ -1844,12 +1875,18 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) } 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; + if (nsid != NVME_NSID_BROADCAST) { + if (!nvme_nsid_valid(n, nsid)) { + return NVME_INVALID_NSID | NVME_DNR; + } + + ns = nvme_ns(n, nsid); + if (unlikely(!ns)) { + return NVME_INVALID_FIELD | NVME_DNR; + } } } else if (nsid && nsid != NVME_NSID_BROADCAST) { - if (nsid > n->num_namespaces) { + if (!nvme_nsid_valid(n, nsid)) { return NVME_INVALID_NSID | NVME_DNR; } @@ -1887,12 +1924,23 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) break; case NVME_VOLATILE_WRITE_CACHE: - if (!(dw11 & 0x1) && blk_enable_write_cache(n->conf.blk)) { - blk_flush(n->conf.blk); + n->features.vwc = dw11 & 0x1; + + for (int i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + + if (!(dw11 & 0x1) && blk_enable_write_cache(ns->blk)) { + blk_flush(ns->blk); + } + + blk_set_enable_write_cache(ns->blk, dw11 & 1); } - 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; @@ -2014,9 +2062,17 @@ static void nvme_process_sq(void *opaque) static void nvme_clear_ctrl(NvmeCtrl *n) { + NvmeNamespace *ns; int i; - blk_drain(n->conf.blk); + for (i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + + nvme_ns_drain(ns); + } for (i = 0; i < n->params.max_ioqpairs + 1; i++) { if (n->sq[i] != NULL) { @@ -2039,7 +2095,15 @@ static void nvme_clear_ctrl(NvmeCtrl *n) n->outstanding_aers = 0; n->qs_created = false; - blk_flush(n->conf.blk); + for (i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + + nvme_ns_flush(ns); + } + n->bar.cc = 0; } @@ -2517,6 +2581,11 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp) params->max_ioqpairs = params->num_queues - 1; } + if (n->namespace.blk) { + warn_report("drive property is deprecated; " + "please use an nvme-ns device instead"); + } + if (params->max_ioqpairs < 1 || params->max_ioqpairs > NVME_MAX_IOQPAIRS) { error_setg(errp, "max_ioqpairs must be between 1 and %d", @@ -2531,11 +2600,6 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp) return; } - if (!n->conf.blk) { - error_setg(errp, "drive property not set"); - return; - } - if (!params->serial) { error_setg(errp, "serial property not set"); return; @@ -2559,11 +2623,10 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp) static void nvme_init_state(NvmeCtrl *n) { - n->num_namespaces = 1; + n->num_namespaces = NVME_MAX_NAMESPACES; /* add one to max_ioqpairs to account for the admin queue pair */ n->reg_size = pow2ceil(sizeof(NvmeBar) + 2 * (n->params.max_ioqpairs + 1) * NVME_DB_SIZE); - 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->temperature = NVME_TEMPERATURE; @@ -2572,34 +2635,41 @@ static void nvme_init_state(NvmeCtrl *n) n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1); } -static void nvme_init_blk(NvmeCtrl *n, Error **errp) +int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) { - if (!blkconf_blocksizes(&n->conf, errp)) { - return; - } - blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk), - false, errp); -} + uint32_t nsid = nvme_nsid(ns); -static void nvme_init_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) -{ - int64_t bs_size; - NvmeIdNs *id_ns = &ns->id_ns; - - bs_size = blk_getlength(n->conf.blk); - if (bs_size < 0) { - error_setg_errno(errp, -bs_size, "could not get backing file size"); - return; + if (nsid > NVME_MAX_NAMESPACES) { + error_setg(errp, "invalid namespace id (must be between 0 and %d)", + NVME_MAX_NAMESPACES); + return -1; } - n->ns_size = bs_size; + if (!nsid) { + for (int i = 1; i <= n->num_namespaces; i++) { + NvmeNamespace *ns = nvme_ns(n, i); + if (!ns) { + nsid = i; + break; + } + } - id_ns->lbaf[0].ds = BDRV_SECTOR_BITS; - id_ns->nsze = cpu_to_le64(nvme_ns_nlbas(n, ns)); + if (!nsid) { + error_setg(errp, "no free namespace id"); + return -1; + } + } else { + if (n->namespaces[nsid - 1]) { + error_setg(errp, "namespace id '%d' is already in use", nsid); + return -1; + } + } - /* no thin provisioning */ - id_ns->ncap = id_ns->nsze; - id_ns->nuse = id_ns->ncap; + trace_pci_nvme_register_namespace(nsid); + + n->namespaces[nsid - 1] = ns; + + return 0; } static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev) @@ -2741,6 +2811,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->nn = cpu_to_le32(n->num_namespaces); id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROES | NVME_ONCS_TIMESTAMP | NVME_ONCS_FEATURES); + + id->vwc = 0x1; id->sgls = cpu_to_le32(NVME_CTRL_SGLS_SUPPORT_NO_ALIGN | NVME_CTRL_SGLS_BITBUCKET); @@ -2751,9 +2823,6 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->psd[0].mp = cpu_to_le16(0x9c4); id->psd[0].enlat = cpu_to_le32(0x10); id->psd[0].exlat = cpu_to_le32(0x4); - if (blk_enable_write_cache(n->conf.blk)) { - id->vwc = 1; - } n->bar.cap = 0; NVME_CAP_SET_MQES(n->bar.cap, 0x7ff); @@ -2769,23 +2838,19 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) static void nvme_realize(PCIDevice *pci_dev, Error **errp) { NvmeCtrl *n = NVME(pci_dev); + NvmeNamespace *ns; Error *local_err = NULL; - int i; - nvme_check_constraints(n, &local_err); if (local_err) { error_propagate(errp, local_err); return; } - nvme_init_state(n); - nvme_init_blk(n, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } + qbus_create_inplace(&n->bus, sizeof(NvmeBus), TYPE_NVME_BUS, + &pci_dev->qdev, n->parent_obj.qdev.id); + nvme_init_state(n); nvme_init_pci(n, pci_dev, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -2794,10 +2859,12 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) nvme_init_ctrl(n, pci_dev); - for (i = 0; i < n->num_namespaces; i++) { - nvme_init_namespace(n, &n->namespaces[i], &local_err); - if (local_err) { - error_propagate(errp, local_err); + /* setup a namespace if the controller drive property was given */ + if (n->namespace.blk) { + ns = &n->namespace; + ns->params.nsid = 1; + + if (nvme_ns_setup(n, ns, errp)) { return; } } @@ -2824,7 +2891,8 @@ static void nvme_exit(PCIDevice *pci_dev) } static Property nvme_props[] = { - DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf), + DEFINE_BLOCK_PROPERTIES_BASE(NvmeCtrl, conf), + DEFINE_PROP_DRIVE("drive", NvmeCtrl, namespace.blk), DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial), @@ -2865,26 +2933,35 @@ static void nvme_instance_init(Object *obj) { NvmeCtrl *s = NVME(obj); - device_add_bootindex_property(obj, &s->conf.bootindex, - "bootindex", "/namespace@1,0", - DEVICE(obj)); + if (s->namespace.blk) { + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/namespace@1,0", + DEVICE(obj)); + } } static const TypeInfo nvme_info = { .name = TYPE_NVME, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(NvmeCtrl), - .class_init = nvme_class_init, .instance_init = nvme_instance_init, + .class_init = nvme_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_PCIE_DEVICE }, { } }, }; +static const TypeInfo nvme_bus_info = { + .name = TYPE_NVME_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(NvmeBus), +}; + static void nvme_register_types(void) { type_register_static(&nvme_info); + type_register_static(&nvme_bus_info); } type_init(nvme_register_types) diff --git a/hw/block/nvme.h b/hw/block/nvme.h index baedcb226cb1..72260f2e8ea9 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -2,6 +2,9 @@ #define HW_NVME_H #include "block/nvme.h" +#include "nvme-ns.h" + +#define NVME_MAX_NAMESPACES 256 typedef struct NvmeParams { char *serial; @@ -135,26 +138,12 @@ typedef struct NvmeCQueue { QTAILQ_HEAD(, NvmeRequest) req_list; } NvmeCQueue; -typedef struct NvmeNamespace { - NvmeIdNs id_ns; -} NvmeNamespace; +#define TYPE_NVME_BUS "nvme-bus" +#define NVME_BUS(obj) OBJECT_CHECK(NvmeBus, (obj), TYPE_NVME_BUS) -static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns) -{ - NvmeIdNs *id_ns = &ns->id_ns; - return &id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; -} - -static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns) -{ - return nvme_ns_lbaf(ns)->ds; -} - -/* convert an LBA to the equivalent in bytes */ -static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) -{ - return lba << nvme_ns_lbads(ns); -} +typedef struct NvmeBus { + BusState parent_bus; +} NvmeBus; #define TYPE_NVME "nvme" #define NVME(obj) \ @@ -166,6 +155,7 @@ typedef struct NvmeFeatureVal { uint16_t temp_thresh_low; }; uint32_t async_config; + uint32_t vwc; } NvmeFeatureVal; typedef struct NvmeCtrl { @@ -173,8 +163,9 @@ typedef struct NvmeCtrl { MemoryRegion iomem; MemoryRegion ctrl_mem; NvmeBar bar; - BlockConf conf; NvmeParams params; + NvmeBus bus; + BlockConf conf; bool qs_created; uint32_t page_size; @@ -185,7 +176,6 @@ typedef struct NvmeCtrl { uint32_t reg_size; uint32_t num_namespaces; uint32_t max_q_ents; - uint64_t ns_size; uint8_t outstanding_aers; uint8_t *cmbuf; uint32_t irq_status; @@ -201,7 +191,8 @@ typedef struct NvmeCtrl { QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue; int aer_queued; - NvmeNamespace *namespaces; + NvmeNamespace namespace; + NvmeNamespace *namespaces[NVME_MAX_NAMESPACES]; NvmeSQueue **sq; NvmeCQueue **cq; NvmeSQueue admin_sq; @@ -210,10 +201,13 @@ typedef struct NvmeCtrl { NvmeFeatureVal features; } NvmeCtrl; -/* calculate the number of LBAs that the namespace can accomodate */ -static inline uint64_t nvme_ns_nlbas(NvmeCtrl *n, NvmeNamespace *ns) +static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) { - return n->ns_size >> nvme_ns_lbads(ns); + if (!nsid || nsid > n->num_namespaces) { + return NULL; + } + + return n->namespaces[nsid - 1]; } static inline NvmeCQueue *nvme_cq(NvmeRequest *req) @@ -224,4 +218,6 @@ static inline NvmeCQueue *nvme_cq(NvmeRequest *req) return n->cq[sq->cqid]; } +int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp); + #endif /* HW_NVME_H */ diff --git a/hw/block/trace-events b/hw/block/trace-events index 7fe119bd625c..52c88e01a090 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -29,6 +29,7 @@ hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int t # nvme.c # nvme traces for successful events +pci_nvme_register_namespace(uint32_t nsid) "nsid %"PRIu32"" 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" @@ -39,11 +40,11 @@ pci_nvme_map_prp(uint64_t trans_len, uint32_t len, uint64_t prp1, uint64_t prp2, pci_nvme_map_sgl(uint16_t cid, uint8_t typ, uint64_t len) "cid %"PRIu16" type 0x%"PRIx8" len %"PRIu64"" pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8" opname \"%s\"" -pci_nvme_rw(uint16_t cid, const char *verb, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" \"%s\" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64"" +pci_nvme_rw(uint16_t cid, const char *verb, uint32_t nsid, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" opname \"%s\" nsid %"PRIu32" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64"" +pci_nvme_rw_cb(uint16_t cid, uint32_t nsid) "cid %"PRIu16" nsid %"PRIu32"" +pci_nvme_write_zeroes(uint16_t cid, uint32_t nsid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" nsid %"PRIu32" slba %"PRIu64" nlb %"PRIu32"" pci_nvme_aio_add(uint16_t cid, void *aio, const char *blkname, uint64_t offset, uint64_t len, const char *opc, void *req) "cid %"PRIu16" aio %p blk \"%s\" offset %"PRIu64" len %"PRIu64" opc \"%s\" req %p" pci_nvme_aio_cb(uint16_t cid, void *aio, const char *blkname, uint64_t offset, uint64_t len, const char *opc, void *req) "cid %"PRIu16" aio %p blk \"%s\" offset %"PRIu64" len %"PRIu64" opc \"%s\" req %p" -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"" @@ -100,7 +101,6 @@ pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or no pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64"" pci_nvme_err_invalid_prp2_missing(void) "PRP2 is null and more data to be transferred" pci_nvme_err_invalid_prp(void) "invalid PRP" -pci_nvme_err_invalid_ns(uint32_t ns, uint32_t limit) "invalid namespace %u not within 1-%u" pci_nvme_err_invalid_opc(uint8_t opc) "invalid opcode 0x%"PRIx8"" pci_nvme_err_invalid_admin_opc(uint8_t opc) "invalid admin opcode 0x%"PRIx8"" pci_nvme_err_invalid_lba_range(uint64_t start, uint64_t len, uint64_t limit) "Invalid LBA start=%"PRIu64" len=%"PRIu64" limit=%"PRIu64"" From patchwork Fri Sep 4 14:19:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 274493 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=-17.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, 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 9BE54C43461 for ; Fri, 4 Sep 2020 14:30:10 +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 5899F206B7 for ; Fri, 4 Sep 2020 14:30:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="oHGo+XXC" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5899F206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:43862 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECjB-0004h8-I0 for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:30:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32834) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaO-0003Ry-Ic; Fri, 04 Sep 2020 10:21:04 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48034) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaL-0002jy-SX; Fri, 04 Sep 2020 10:21:04 -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 469A5BFB59; Fri, 4 Sep 2020 14:20:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229237; bh=1d1HFAh873gdEd3I1qfubQTAAUIG3Kt0tglKE7xxg+o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oHGo+XXC3rNgVuHnel92FEJ1+HW0MPCtUJ4Rb06nsGUYLX8l9UHkizabqTzDHrVcF pL4292Di60harLctFdd/CjidefMAlPFBZK1ZALeFZxg2muN8JY/KCdN1bllquFCqod Y5h7Qe73RYhcTK985qdrE4ql3pk397ey4RVK2kZ1eud+v8p7HJ10xW8QxpJLeR5gDA SsKVn93T+A1MtaTSWjIXHpm+4gIMVErWT3T9+zrOW64hybtpNrF1+RRrZM4+w9BqoI EzfUEk/fap6+YaL9QaxpUJV/0P4dRcQUDfOYOwJpp3qF0M49BAytmmn6xnaoV3l7Vw ILFu7zyImNB6Q== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 16/17] pci: allocate pci id for nvme Date: Fri, 4 Sep 2020 16:19:55 +0200 Message-Id: <20200904141956.576630-17-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Gerd Hoffmann , Klaus Jensen , Maxim Levitsky Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen The emulated nvme device (hw/block/nvme.c) is currently using an internal Intel device id. Prepare to change that by allocating a device id under the 1b36 (Red Hat, Inc.) vendor id. Signed-off-by: Klaus Jensen Acked-by: Keith Busch Acked-by: Gerd Hoffmann Reviewed-by: Maxim Levitsky --- MAINTAINERS | 1 + docs/specs/nvme.txt | 23 +++++++++++++++++++++++ docs/specs/pci-ids.txt | 1 + include/hw/pci/pci.h | 1 + 4 files changed, 26 insertions(+) create mode 100644 docs/specs/nvme.txt diff --git a/MAINTAINERS b/MAINTAINERS index b233da2a7379..5de612aae381 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1861,6 +1861,7 @@ L: qemu-block@nongnu.org S: Supported F: hw/block/nvme* F: tests/qtest/nvme-test.c +F: docs/specs/nvme.txt T: git git://git.infradead.org/qemu-nvme.git nvme-next megasas diff --git a/docs/specs/nvme.txt b/docs/specs/nvme.txt new file mode 100644 index 000000000000..56d393884e7a --- /dev/null +++ b/docs/specs/nvme.txt @@ -0,0 +1,23 @@ +NVM Express Controller +====================== + +The nvme device (-device nvme) emulates an NVM Express Controller. + + +Reference Specifications +------------------------ + +The device currently implements most mandatory features of NVMe v1.3d, see + + https://nvmexpress.org/resources/specifications/ + +for the specification. + + +Known issues +------------ + +* The accounting numbers in the SMART/Health are reset across power cycles + +* Interrupt Coalescing is not supported and is disabled by default in volation + of the specification. diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt index 4d53e5c7d9d5..abbdbca6be38 100644 --- a/docs/specs/pci-ids.txt +++ b/docs/specs/pci-ids.txt @@ -63,6 +63,7 @@ PCI devices (other than virtio): 1b36:000b PCIe Expander Bridge (-device pxb-pcie) 1b36:000d PCI xhci usb host adapter 1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c +1b36:0010 PCIe NVMe device (-device nvme) All these devices are documented in docs/specs. diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 896cef9ad476..f7123c5b8a2e 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -105,6 +105,7 @@ extern bool pci_available; #define PCI_DEVICE_ID_REDHAT_XHCI 0x000d #define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e #define PCI_DEVICE_ID_REDHAT_MDPY 0x000f +#define PCI_DEVICE_ID_REDHAT_NVME 0x0010 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 #define FMT_PCIBUS PRIx64 From patchwork Fri Sep 4 14:19: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: 274497 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, 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 A3207C433E2 for ; Fri, 4 Sep 2020 14:25:04 +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 643C0206B7 for ; Fri, 4 Sep 2020 14:25:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=irrelevant.dk header.i=@irrelevant.dk header.b="UWTRuxdW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 643C0206B7 Authentication-Results: mail.kernel.org; dmarc=fail (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]:49898 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kECeF-0003rB-Cm for qemu-devel@archiver.kernel.org; Fri, 04 Sep 2020 10:25:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32848) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaP-0003Vg-QV; Fri, 04 Sep 2020 10:21:05 -0400 Received: from charlie.dont.surf ([128.199.63.193]:48036) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kECaM-0002kF-Fk; Fri, 04 Sep 2020 10:21:05 -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 AC944BFBE9; Fri, 4 Sep 2020 14:20:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=irrelevant.dk; s=default; t=1599229238; bh=5ZjDoTIIr492u+clFrXjEhMBLTXUh19lollxZUe3VI8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UWTRuxdWg+SN9qos0NbTmmMnmIbqDh6x9Yn53B/nGsh5FJP6eMypccPYrYzQMPQIY UJPUAUxI4Z+VAUgwg7/wQPpZIHCI9+muiCgofgLBwbwKKJbXCf8lhSggMAzD4vbkvs aX767w+ALtWMsyYjGnecnhtwTHpYEtL55oY95IQ2gXsYBB+qOa/jTlZWKRHghIsx5k AZeQCr4osjNuV2SHCozX0iAFQLxduR4N+JA/KQQwdgN8EQ/wU+gfuDVzubKZWhVbGy DgZ8plO4Ke3JnhGkigQVTTOfKbYkya330fZ33VbnWKXNai+4dVyeMVFNM+y3pc0XmN k0muURni4S2fg== From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 17/17] hw/block/nvme: change controller pci id Date: Fri, 4 Sep 2020 16:19:56 +0200 Message-Id: <20200904141956.576630-18-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200904141956.576630-1-its@irrelevant.dk> References: <20200904141956.576630-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/09/04 10:20:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no 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 , Eduardo Habkost , qemu-block@nongnu.org, "Michael S. Tsirkin" , Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen , Maxim Levitsky Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen There are two reasons for changing this: 1. The nvme device currently uses an internal Intel device id. 2. Since commits "nvme: fix write zeroes offset and count" and "nvme: support multiple namespaces" the controller device no longer has the quirks that the Linux kernel think it has. As the quirks are applied based on pci vendor and device id, change them to get rid of the quirks. To keep backward compatibility, add a new 'x-use-intel-id' parameter to the nvme device to force use of the Intel vendor and device id. This is off by default but add a compat property to set this for 5.1 machines and older. Signed-off-by: Klaus Jensen Reviewed-by: Keith Busch Reviewed-by: Maxim Levitsky --- hw/block/nvme.c | 12 ++++++++++-- hw/block/nvme.h | 1 + hw/core/machine.c | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 453d3a89d475..8018f8679366 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -2749,6 +2749,15 @@ static void nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp) pci_conf[PCI_INTERRUPT_PIN] = 1; pci_config_set_prog_interface(pci_conf, 0x2); + + if (n->params.use_intel_id) { + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); + pci_config_set_device_id(pci_conf, 0x5846); + } else { + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REDHAT); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REDHAT_NVME); + } + pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_EXPRESS); pcie_endpoint_cap_init(pci_dev, 0x80); @@ -2903,6 +2912,7 @@ static Property nvme_props[] = { DEFINE_PROP_UINT8("aerl", NvmeCtrl, params.aerl, 3), DEFINE_PROP_UINT32("aer_max_queued", NvmeCtrl, params.aer_max_queued, 64), DEFINE_PROP_UINT8("mdts", NvmeCtrl, params.mdts, 7), + DEFINE_PROP_BOOL("x-use-intel-id", NvmeCtrl, params.use_intel_id, false), DEFINE_PROP_END_OF_LIST(), }; @@ -2919,8 +2929,6 @@ static void nvme_class_init(ObjectClass *oc, void *data) pc->realize = nvme_realize; pc->exit = nvme_exit; pc->class_id = PCI_CLASS_STORAGE_EXPRESS; - pc->vendor_id = PCI_VENDOR_ID_INTEL; - pc->device_id = 0x5845; pc->revision = 2; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 72260f2e8ea9..a734a5e1370d 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -15,6 +15,7 @@ typedef struct NvmeParams { uint8_t aerl; uint32_t aer_max_queued; uint8_t mdts; + bool use_intel_id; } NvmeParams; typedef struct NvmeAsyncEvent { diff --git a/hw/core/machine.c b/hw/core/machine.c index ea26d612374d..67990232528c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -34,6 +34,7 @@ GlobalProperty hw_compat_5_1[] = { { "vhost-user-scsi", "num_queues", "1"}, { "virtio-blk-device", "num-queues", "1"}, { "virtio-scsi-device", "num_queues", "1"}, + { "nvme", "x-use-intel-id", "on"}, }; const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1);