From nobody Tue Oct 28 04:18:23 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1515576419523215.04791647973695; Wed, 10 Jan 2018 01:26:59 -0800 (PST) Received: from localhost ([::1]:56179 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eZCew-0003fJ-JO for importer@patchew.org; Wed, 10 Jan 2018 04:26:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49179) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eZCYB-00061K-G4 for qemu-devel@nongnu.org; Wed, 10 Jan 2018 04:20:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eZCY7-0000QK-I7 for qemu-devel@nongnu.org; Wed, 10 Jan 2018 04:19:59 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52708) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eZCXw-0000I2-3c; Wed, 10 Jan 2018 04:19:44 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 479C521BB7; Wed, 10 Jan 2018 09:19:43 +0000 (UTC) Received: from lemon.usersys.redhat.com (ovpn-12-52.pek2.redhat.com [10.72.12.52]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2794C7B8D3; Wed, 10 Jan 2018 09:19:33 +0000 (UTC) From: Fam Zheng To: qemu-devel@nongnu.org Date: Wed, 10 Jan 2018 17:18:44 +0800 Message-Id: <20180110091846.10699-8-famz@redhat.com> In-Reply-To: <20180110091846.10699-1-famz@redhat.com> References: <20180110091846.10699-1-famz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 10 Jan 2018 09:19:43 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 7/9] block: Move NVMe constants to a separate header X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , qemu-block@nongnu.org, Markus Armbruster , Max Reitz , Keith Busch , Stefan Hajnoczi , Paolo Bonzini , Karl Rister Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block/nvme.c | 7 +- hw/block/nvme.h | 698 +----------------------------------------------= --- include/block/nvme.h | 700 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 702 insertions(+), 703 deletions(-) create mode 100644 include/block/nvme.h diff --git a/block/nvme.c b/block/nvme.c index 7042743929..0cf92b397c 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -22,12 +22,7 @@ #include "block/block_int.h" #include "trace.h" =20 -/* TODO: Move nvme spec definitions from hw/block/nvme.h into a separate f= ile - * that doesn't depend on dma/pci headers. */ -#include "sysemu/dma.h" -#include "hw/pci/pci.h" -#include "hw/block/block.h" -#include "hw/block/nvme.h" +#include "block/nvme.h" =20 #define NVME_SQ_ENTRY_BYTES 64 #define NVME_CQ_ENTRY_BYTES 16 diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 6aab338ff5..59a1504018 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -1,703 +1,7 @@ #ifndef HW_NVME_H #define HW_NVME_H #include "qemu/cutils.h" - -typedef struct NvmeBar { - uint64_t cap; - uint32_t vs; - uint32_t intms; - uint32_t intmc; - uint32_t cc; - uint32_t rsvd1; - uint32_t csts; - uint32_t nssrc; - uint32_t aqa; - uint64_t asq; - uint64_t acq; - uint32_t cmbloc; - uint32_t cmbsz; -} NvmeBar; - -enum NvmeCapShift { - CAP_MQES_SHIFT =3D 0, - CAP_CQR_SHIFT =3D 16, - CAP_AMS_SHIFT =3D 17, - CAP_TO_SHIFT =3D 24, - CAP_DSTRD_SHIFT =3D 32, - CAP_NSSRS_SHIFT =3D 33, - CAP_CSS_SHIFT =3D 37, - CAP_MPSMIN_SHIFT =3D 48, - CAP_MPSMAX_SHIFT =3D 52, -}; - -enum NvmeCapMask { - CAP_MQES_MASK =3D 0xffff, - CAP_CQR_MASK =3D 0x1, - CAP_AMS_MASK =3D 0x3, - CAP_TO_MASK =3D 0xff, - CAP_DSTRD_MASK =3D 0xf, - CAP_NSSRS_MASK =3D 0x1, - CAP_CSS_MASK =3D 0xff, - CAP_MPSMIN_MASK =3D 0xf, - CAP_MPSMAX_MASK =3D 0xf, -}; - -#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK) -#define NVME_CAP_CQR(cap) (((cap) >> CAP_CQR_SHIFT) & CAP_CQR_MASK) -#define NVME_CAP_AMS(cap) (((cap) >> CAP_AMS_SHIFT) & CAP_AMS_MASK) -#define NVME_CAP_TO(cap) (((cap) >> CAP_TO_SHIFT) & CAP_TO_MASK) -#define NVME_CAP_DSTRD(cap) (((cap) >> CAP_DSTRD_SHIFT) & CAP_DSTRD_MASK) -#define NVME_CAP_NSSRS(cap) (((cap) >> CAP_NSSRS_SHIFT) & CAP_NSSRS_MASK) -#define NVME_CAP_CSS(cap) (((cap) >> CAP_CSS_SHIFT) & CAP_CSS_MASK) -#define NVME_CAP_MPSMIN(cap)(((cap) >> CAP_MPSMIN_SHIFT) & CAP_MPSMIN_MASK) -#define NVME_CAP_MPSMAX(cap)(((cap) >> CAP_MPSMAX_SHIFT) & CAP_MPSMAX_MASK) - -#define NVME_CAP_SET_MQES(cap, val) (cap |=3D (uint64_t)(val & CAP_MQES_= MASK) \ - << CAP_MQES_SHI= FT) -#define NVME_CAP_SET_CQR(cap, val) (cap |=3D (uint64_t)(val & CAP_CQR_M= ASK) \ - << CAP_CQR_SHIF= T) -#define NVME_CAP_SET_AMS(cap, val) (cap |=3D (uint64_t)(val & CAP_AMS_M= ASK) \ - << CAP_AMS_SHIF= T) -#define NVME_CAP_SET_TO(cap, val) (cap |=3D (uint64_t)(val & CAP_TO_MA= SK) \ - << CAP_TO_SHIFT) -#define NVME_CAP_SET_DSTRD(cap, val) (cap |=3D (uint64_t)(val & CAP_DSTRD= _MASK) \ - << CAP_DSTRD_SH= IFT) -#define NVME_CAP_SET_NSSRS(cap, val) (cap |=3D (uint64_t)(val & CAP_NSSRS= _MASK) \ - << CAP_NSSRS_SH= IFT) -#define NVME_CAP_SET_CSS(cap, val) (cap |=3D (uint64_t)(val & CAP_CSS_M= ASK) \ - << CAP_CSS_SHIF= T) -#define NVME_CAP_SET_MPSMIN(cap, val) (cap |=3D (uint64_t)(val & CAP_MPSMI= N_MASK)\ - << CAP_MPSMIN_S= HIFT) -#define NVME_CAP_SET_MPSMAX(cap, val) (cap |=3D (uint64_t)(val & CAP_MPSMA= X_MASK)\ - << CAP_MPSMAX_= SHIFT) - -enum NvmeCcShift { - CC_EN_SHIFT =3D 0, - CC_CSS_SHIFT =3D 4, - CC_MPS_SHIFT =3D 7, - CC_AMS_SHIFT =3D 11, - CC_SHN_SHIFT =3D 14, - CC_IOSQES_SHIFT =3D 16, - CC_IOCQES_SHIFT =3D 20, -}; - -enum NvmeCcMask { - CC_EN_MASK =3D 0x1, - CC_CSS_MASK =3D 0x7, - CC_MPS_MASK =3D 0xf, - CC_AMS_MASK =3D 0x7, - CC_SHN_MASK =3D 0x3, - CC_IOSQES_MASK =3D 0xf, - CC_IOCQES_MASK =3D 0xf, -}; - -#define NVME_CC_EN(cc) ((cc >> CC_EN_SHIFT) & CC_EN_MASK) -#define NVME_CC_CSS(cc) ((cc >> CC_CSS_SHIFT) & CC_CSS_MASK) -#define NVME_CC_MPS(cc) ((cc >> CC_MPS_SHIFT) & CC_MPS_MASK) -#define NVME_CC_AMS(cc) ((cc >> CC_AMS_SHIFT) & CC_AMS_MASK) -#define NVME_CC_SHN(cc) ((cc >> CC_SHN_SHIFT) & CC_SHN_MASK) -#define NVME_CC_IOSQES(cc) ((cc >> CC_IOSQES_SHIFT) & CC_IOSQES_MASK) -#define NVME_CC_IOCQES(cc) ((cc >> CC_IOCQES_SHIFT) & CC_IOCQES_MASK) - -enum NvmeCstsShift { - CSTS_RDY_SHIFT =3D 0, - CSTS_CFS_SHIFT =3D 1, - CSTS_SHST_SHIFT =3D 2, - CSTS_NSSRO_SHIFT =3D 4, -}; - -enum NvmeCstsMask { - CSTS_RDY_MASK =3D 0x1, - CSTS_CFS_MASK =3D 0x1, - CSTS_SHST_MASK =3D 0x3, - CSTS_NSSRO_MASK =3D 0x1, -}; - -enum NvmeCsts { - NVME_CSTS_READY =3D 1 << CSTS_RDY_SHIFT, - NVME_CSTS_FAILED =3D 1 << CSTS_CFS_SHIFT, - NVME_CSTS_SHST_NORMAL =3D 0 << CSTS_SHST_SHIFT, - NVME_CSTS_SHST_PROGRESS =3D 1 << CSTS_SHST_SHIFT, - NVME_CSTS_SHST_COMPLETE =3D 2 << CSTS_SHST_SHIFT, - NVME_CSTS_NSSRO =3D 1 << CSTS_NSSRO_SHIFT, -}; - -#define NVME_CSTS_RDY(csts) ((csts >> CSTS_RDY_SHIFT) & CSTS_RDY_MAS= K) -#define NVME_CSTS_CFS(csts) ((csts >> CSTS_CFS_SHIFT) & CSTS_CFS_MAS= K) -#define NVME_CSTS_SHST(csts) ((csts >> CSTS_SHST_SHIFT) & CSTS_SHST_MA= SK) -#define NVME_CSTS_NSSRO(csts) ((csts >> CSTS_NSSRO_SHIFT) & CSTS_NSSRO_M= ASK) - -enum NvmeAqaShift { - AQA_ASQS_SHIFT =3D 0, - AQA_ACQS_SHIFT =3D 16, -}; - -enum NvmeAqaMask { - AQA_ASQS_MASK =3D 0xfff, - AQA_ACQS_MASK =3D 0xfff, -}; - -#define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK) -#define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK) - -enum NvmeCmblocShift { - CMBLOC_BIR_SHIFT =3D 0, - CMBLOC_OFST_SHIFT =3D 12, -}; - -enum NvmeCmblocMask { - CMBLOC_BIR_MASK =3D 0x7, - CMBLOC_OFST_MASK =3D 0xfffff, -}; - -#define NVME_CMBLOC_BIR(cmbloc) ((cmbloc >> CMBLOC_BIR_SHIFT) & \ - CMBLOC_BIR_MASK) -#define NVME_CMBLOC_OFST(cmbloc)((cmbloc >> CMBLOC_OFST_SHIFT) & \ - CMBLOC_OFST_MASK) - -#define NVME_CMBLOC_SET_BIR(cmbloc, val) \ - (cmbloc |=3D (uint64_t)(val & CMBLOC_BIR_MASK) << CMBLOC_BIR_SHIFT) -#define NVME_CMBLOC_SET_OFST(cmbloc, val) \ - (cmbloc |=3D (uint64_t)(val & CMBLOC_OFST_MASK) << CMBLOC_OFST_SHIFT) - -enum NvmeCmbszShift { - CMBSZ_SQS_SHIFT =3D 0, - CMBSZ_CQS_SHIFT =3D 1, - CMBSZ_LISTS_SHIFT =3D 2, - CMBSZ_RDS_SHIFT =3D 3, - CMBSZ_WDS_SHIFT =3D 4, - CMBSZ_SZU_SHIFT =3D 8, - CMBSZ_SZ_SHIFT =3D 12, -}; - -enum NvmeCmbszMask { - CMBSZ_SQS_MASK =3D 0x1, - CMBSZ_CQS_MASK =3D 0x1, - CMBSZ_LISTS_MASK =3D 0x1, - CMBSZ_RDS_MASK =3D 0x1, - CMBSZ_WDS_MASK =3D 0x1, - CMBSZ_SZU_MASK =3D 0xf, - CMBSZ_SZ_MASK =3D 0xfffff, -}; - -#define NVME_CMBSZ_SQS(cmbsz) ((cmbsz >> CMBSZ_SQS_SHIFT) & CMBSZ_SQS_M= ASK) -#define NVME_CMBSZ_CQS(cmbsz) ((cmbsz >> CMBSZ_CQS_SHIFT) & CMBSZ_CQS_M= ASK) -#define NVME_CMBSZ_LISTS(cmbsz)((cmbsz >> CMBSZ_LISTS_SHIFT) & CMBSZ_LISTS= _MASK) -#define NVME_CMBSZ_RDS(cmbsz) ((cmbsz >> CMBSZ_RDS_SHIFT) & CMBSZ_RDS_M= ASK) -#define NVME_CMBSZ_WDS(cmbsz) ((cmbsz >> CMBSZ_WDS_SHIFT) & CMBSZ_WDS_M= ASK) -#define NVME_CMBSZ_SZU(cmbsz) ((cmbsz >> CMBSZ_SZU_SHIFT) & CMBSZ_SZU_M= ASK) -#define NVME_CMBSZ_SZ(cmbsz) ((cmbsz >> CMBSZ_SZ_SHIFT) & CMBSZ_SZ_MA= SK) - -#define NVME_CMBSZ_SET_SQS(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_SQS_MASK) << CMBSZ_SQS_SHIFT) -#define NVME_CMBSZ_SET_CQS(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_CQS_MASK) << CMBSZ_CQS_SHIFT) -#define NVME_CMBSZ_SET_LISTS(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_LISTS_MASK) << CMBSZ_LISTS_SHIFT) -#define NVME_CMBSZ_SET_RDS(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_RDS_MASK) << CMBSZ_RDS_SHIFT) -#define NVME_CMBSZ_SET_WDS(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_WDS_MASK) << CMBSZ_WDS_SHIFT) -#define NVME_CMBSZ_SET_SZU(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_SZU_MASK) << CMBSZ_SZU_SHIFT) -#define NVME_CMBSZ_SET_SZ(cmbsz, val) \ - (cmbsz |=3D (uint64_t)(val & CMBSZ_SZ_MASK) << CMBSZ_SZ_SHIFT) - -#define NVME_CMBSZ_GETSIZE(cmbsz) \ - (NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz)))) - -typedef struct NvmeCmd { - uint8_t opcode; - uint8_t fuse; - uint16_t cid; - uint32_t nsid; - uint64_t res1; - uint64_t mptr; - uint64_t prp1; - uint64_t prp2; - uint32_t cdw10; - uint32_t cdw11; - uint32_t cdw12; - uint32_t cdw13; - uint32_t cdw14; - uint32_t cdw15; -} NvmeCmd; - -enum NvmeAdminCommands { - NVME_ADM_CMD_DELETE_SQ =3D 0x00, - NVME_ADM_CMD_CREATE_SQ =3D 0x01, - NVME_ADM_CMD_GET_LOG_PAGE =3D 0x02, - NVME_ADM_CMD_DELETE_CQ =3D 0x04, - NVME_ADM_CMD_CREATE_CQ =3D 0x05, - NVME_ADM_CMD_IDENTIFY =3D 0x06, - NVME_ADM_CMD_ABORT =3D 0x08, - NVME_ADM_CMD_SET_FEATURES =3D 0x09, - NVME_ADM_CMD_GET_FEATURES =3D 0x0a, - NVME_ADM_CMD_ASYNC_EV_REQ =3D 0x0c, - NVME_ADM_CMD_ACTIVATE_FW =3D 0x10, - NVME_ADM_CMD_DOWNLOAD_FW =3D 0x11, - NVME_ADM_CMD_FORMAT_NVM =3D 0x80, - NVME_ADM_CMD_SECURITY_SEND =3D 0x81, - NVME_ADM_CMD_SECURITY_RECV =3D 0x82, -}; - -enum NvmeIoCommands { - NVME_CMD_FLUSH =3D 0x00, - NVME_CMD_WRITE =3D 0x01, - NVME_CMD_READ =3D 0x02, - NVME_CMD_WRITE_UNCOR =3D 0x04, - NVME_CMD_COMPARE =3D 0x05, - NVME_CMD_WRITE_ZEROS =3D 0x08, - NVME_CMD_DSM =3D 0x09, -}; - -typedef struct NvmeDeleteQ { - uint8_t opcode; - uint8_t flags; - uint16_t cid; - uint32_t rsvd1[9]; - uint16_t qid; - uint16_t rsvd10; - uint32_t rsvd11[5]; -} NvmeDeleteQ; - -typedef struct NvmeCreateCq { - uint8_t opcode; - uint8_t flags; - uint16_t cid; - uint32_t rsvd1[5]; - uint64_t prp1; - uint64_t rsvd8; - uint16_t cqid; - uint16_t qsize; - uint16_t cq_flags; - uint16_t irq_vector; - uint32_t rsvd12[4]; -} NvmeCreateCq; - -#define NVME_CQ_FLAGS_PC(cq_flags) (cq_flags & 0x1) -#define NVME_CQ_FLAGS_IEN(cq_flags) ((cq_flags >> 1) & 0x1) - -typedef struct NvmeCreateSq { - uint8_t opcode; - uint8_t flags; - uint16_t cid; - uint32_t rsvd1[5]; - uint64_t prp1; - uint64_t rsvd8; - uint16_t sqid; - uint16_t qsize; - uint16_t sq_flags; - uint16_t cqid; - uint32_t rsvd12[4]; -} NvmeCreateSq; - -#define NVME_SQ_FLAGS_PC(sq_flags) (sq_flags & 0x1) -#define NVME_SQ_FLAGS_QPRIO(sq_flags) ((sq_flags >> 1) & 0x3) - -enum NvmeQueueFlags { - NVME_Q_PC =3D 1, - NVME_Q_PRIO_URGENT =3D 0, - NVME_Q_PRIO_HIGH =3D 1, - NVME_Q_PRIO_NORMAL =3D 2, - NVME_Q_PRIO_LOW =3D 3, -}; - -typedef struct NvmeIdentify { - uint8_t opcode; - uint8_t flags; - uint16_t cid; - uint32_t nsid; - uint64_t rsvd2[2]; - uint64_t prp1; - uint64_t prp2; - uint32_t cns; - uint32_t rsvd11[5]; -} NvmeIdentify; - -typedef struct NvmeRwCmd { - uint8_t opcode; - uint8_t flags; - uint16_t cid; - uint32_t nsid; - uint64_t rsvd2; - uint64_t mptr; - uint64_t prp1; - uint64_t prp2; - uint64_t slba; - uint16_t nlb; - uint16_t control; - uint32_t dsmgmt; - uint32_t reftag; - uint16_t apptag; - uint16_t appmask; -} NvmeRwCmd; - -enum { - NVME_RW_LR =3D 1 << 15, - NVME_RW_FUA =3D 1 << 14, - NVME_RW_DSM_FREQ_UNSPEC =3D 0, - NVME_RW_DSM_FREQ_TYPICAL =3D 1, - NVME_RW_DSM_FREQ_RARE =3D 2, - NVME_RW_DSM_FREQ_READS =3D 3, - NVME_RW_DSM_FREQ_WRITES =3D 4, - NVME_RW_DSM_FREQ_RW =3D 5, - NVME_RW_DSM_FREQ_ONCE =3D 6, - NVME_RW_DSM_FREQ_PREFETCH =3D 7, - NVME_RW_DSM_FREQ_TEMP =3D 8, - NVME_RW_DSM_LATENCY_NONE =3D 0 << 4, - NVME_RW_DSM_LATENCY_IDLE =3D 1 << 4, - NVME_RW_DSM_LATENCY_NORM =3D 2 << 4, - NVME_RW_DSM_LATENCY_LOW =3D 3 << 4, - NVME_RW_DSM_SEQ_REQ =3D 1 << 6, - NVME_RW_DSM_COMPRESSED =3D 1 << 7, - NVME_RW_PRINFO_PRACT =3D 1 << 13, - NVME_RW_PRINFO_PRCHK_GUARD =3D 1 << 12, - NVME_RW_PRINFO_PRCHK_APP =3D 1 << 11, - NVME_RW_PRINFO_PRCHK_REF =3D 1 << 10, -}; - -typedef struct NvmeDsmCmd { - uint8_t opcode; - uint8_t flags; - uint16_t cid; - uint32_t nsid; - uint64_t rsvd2[2]; - uint64_t prp1; - uint64_t prp2; - uint32_t nr; - uint32_t attributes; - uint32_t rsvd12[4]; -} NvmeDsmCmd; - -enum { - NVME_DSMGMT_IDR =3D 1 << 0, - NVME_DSMGMT_IDW =3D 1 << 1, - NVME_DSMGMT_AD =3D 1 << 2, -}; - -typedef struct NvmeDsmRange { - uint32_t cattr; - uint32_t nlb; - uint64_t slba; -} NvmeDsmRange; - -enum NvmeAsyncEventRequest { - NVME_AER_TYPE_ERROR =3D 0, - NVME_AER_TYPE_SMART =3D 1, - NVME_AER_TYPE_IO_SPECIFIC =3D 6, - NVME_AER_TYPE_VENDOR_SPECIFIC =3D 7, - NVME_AER_INFO_ERR_INVALID_SQ =3D 0, - NVME_AER_INFO_ERR_INVALID_DB =3D 1, - NVME_AER_INFO_ERR_DIAG_FAIL =3D 2, - NVME_AER_INFO_ERR_PERS_INTERNAL_ERR =3D 3, - NVME_AER_INFO_ERR_TRANS_INTERNAL_ERR =3D 4, - NVME_AER_INFO_ERR_FW_IMG_LOAD_ERR =3D 5, - NVME_AER_INFO_SMART_RELIABILITY =3D 0, - NVME_AER_INFO_SMART_TEMP_THRESH =3D 1, - NVME_AER_INFO_SMART_SPARE_THRESH =3D 2, -}; - -typedef struct NvmeAerResult { - uint8_t event_type; - uint8_t event_info; - uint8_t log_page; - uint8_t resv; -} NvmeAerResult; - -typedef struct NvmeCqe { - uint32_t result; - uint32_t rsvd; - uint16_t sq_head; - uint16_t sq_id; - uint16_t cid; - uint16_t status; -} NvmeCqe; - -enum NvmeStatusCodes { - NVME_SUCCESS =3D 0x0000, - NVME_INVALID_OPCODE =3D 0x0001, - NVME_INVALID_FIELD =3D 0x0002, - NVME_CID_CONFLICT =3D 0x0003, - NVME_DATA_TRAS_ERROR =3D 0x0004, - NVME_POWER_LOSS_ABORT =3D 0x0005, - NVME_INTERNAL_DEV_ERROR =3D 0x0006, - NVME_CMD_ABORT_REQ =3D 0x0007, - NVME_CMD_ABORT_SQ_DEL =3D 0x0008, - NVME_CMD_ABORT_FAILED_FUSE =3D 0x0009, - NVME_CMD_ABORT_MISSING_FUSE =3D 0x000a, - NVME_INVALID_NSID =3D 0x000b, - NVME_CMD_SEQ_ERROR =3D 0x000c, - NVME_LBA_RANGE =3D 0x0080, - NVME_CAP_EXCEEDED =3D 0x0081, - NVME_NS_NOT_READY =3D 0x0082, - NVME_NS_RESV_CONFLICT =3D 0x0083, - NVME_INVALID_CQID =3D 0x0100, - NVME_INVALID_QID =3D 0x0101, - NVME_MAX_QSIZE_EXCEEDED =3D 0x0102, - NVME_ACL_EXCEEDED =3D 0x0103, - NVME_RESERVED =3D 0x0104, - NVME_AER_LIMIT_EXCEEDED =3D 0x0105, - NVME_INVALID_FW_SLOT =3D 0x0106, - NVME_INVALID_FW_IMAGE =3D 0x0107, - NVME_INVALID_IRQ_VECTOR =3D 0x0108, - NVME_INVALID_LOG_ID =3D 0x0109, - NVME_INVALID_FORMAT =3D 0x010a, - NVME_FW_REQ_RESET =3D 0x010b, - NVME_INVALID_QUEUE_DEL =3D 0x010c, - NVME_FID_NOT_SAVEABLE =3D 0x010d, - NVME_FID_NOT_NSID_SPEC =3D 0x010f, - NVME_FW_REQ_SUSYSTEM_RESET =3D 0x0110, - NVME_CONFLICTING_ATTRS =3D 0x0180, - NVME_INVALID_PROT_INFO =3D 0x0181, - NVME_WRITE_TO_RO =3D 0x0182, - NVME_WRITE_FAULT =3D 0x0280, - NVME_UNRECOVERED_READ =3D 0x0281, - NVME_E2E_GUARD_ERROR =3D 0x0282, - NVME_E2E_APP_ERROR =3D 0x0283, - NVME_E2E_REF_ERROR =3D 0x0284, - NVME_CMP_FAILURE =3D 0x0285, - NVME_ACCESS_DENIED =3D 0x0286, - NVME_MORE =3D 0x2000, - NVME_DNR =3D 0x4000, - NVME_NO_COMPLETE =3D 0xffff, -}; - -typedef struct NvmeFwSlotInfoLog { - uint8_t afi; - uint8_t reserved1[7]; - uint8_t frs1[8]; - uint8_t frs2[8]; - uint8_t frs3[8]; - uint8_t frs4[8]; - uint8_t frs5[8]; - uint8_t frs6[8]; - uint8_t frs7[8]; - uint8_t reserved2[448]; -} NvmeFwSlotInfoLog; - -typedef struct NvmeErrorLog { - uint64_t error_count; - uint16_t sqid; - uint16_t cid; - uint16_t status_field; - uint16_t param_error_location; - uint64_t lba; - uint32_t nsid; - uint8_t vs; - uint8_t resv[35]; -} NvmeErrorLog; - -typedef struct NvmeSmartLog { - uint8_t critical_warning; - uint8_t temperature[2]; - uint8_t available_spare; - uint8_t available_spare_threshold; - uint8_t percentage_used; - uint8_t reserved1[26]; - uint64_t data_units_read[2]; - uint64_t data_units_written[2]; - uint64_t host_read_commands[2]; - uint64_t host_write_commands[2]; - uint64_t controller_busy_time[2]; - uint64_t power_cycles[2]; - uint64_t power_on_hours[2]; - uint64_t unsafe_shutdowns[2]; - uint64_t media_errors[2]; - uint64_t number_of_error_log_entries[2]; - uint8_t reserved2[320]; -} NvmeSmartLog; - -enum NvmeSmartWarn { - NVME_SMART_SPARE =3D 1 << 0, - NVME_SMART_TEMPERATURE =3D 1 << 1, - NVME_SMART_RELIABILITY =3D 1 << 2, - NVME_SMART_MEDIA_READ_ONLY =3D 1 << 3, - NVME_SMART_FAILED_VOLATILE_MEDIA =3D 1 << 4, -}; - -enum LogIdentifier { - NVME_LOG_ERROR_INFO =3D 0x01, - NVME_LOG_SMART_INFO =3D 0x02, - NVME_LOG_FW_SLOT_INFO =3D 0x03, -}; - -typedef struct NvmePSD { - uint16_t mp; - uint16_t reserved; - uint32_t enlat; - uint32_t exlat; - uint8_t rrt; - uint8_t rrl; - uint8_t rwt; - uint8_t rwl; - uint8_t resv[16]; -} NvmePSD; - -typedef struct NvmeIdCtrl { - uint16_t vid; - uint16_t ssvid; - uint8_t sn[20]; - uint8_t mn[40]; - uint8_t fr[8]; - uint8_t rab; - uint8_t ieee[3]; - uint8_t cmic; - uint8_t mdts; - uint8_t rsvd255[178]; - uint16_t oacs; - uint8_t acl; - uint8_t aerl; - uint8_t frmw; - uint8_t lpa; - uint8_t elpe; - uint8_t npss; - uint8_t rsvd511[248]; - uint8_t sqes; - uint8_t cqes; - uint16_t rsvd515; - uint32_t nn; - uint16_t oncs; - uint16_t fuses; - uint8_t fna; - uint8_t vwc; - uint16_t awun; - uint16_t awupf; - uint8_t rsvd703[174]; - uint8_t rsvd2047[1344]; - NvmePSD psd[32]; - uint8_t vs[1024]; -} NvmeIdCtrl; - -enum NvmeIdCtrlOacs { - NVME_OACS_SECURITY =3D 1 << 0, - NVME_OACS_FORMAT =3D 1 << 1, - NVME_OACS_FW =3D 1 << 2, -}; - -enum NvmeIdCtrlOncs { - NVME_ONCS_COMPARE =3D 1 << 0, - NVME_ONCS_WRITE_UNCORR =3D 1 << 1, - NVME_ONCS_DSM =3D 1 << 2, - NVME_ONCS_WRITE_ZEROS =3D 1 << 3, - NVME_ONCS_FEATURES =3D 1 << 4, - NVME_ONCS_RESRVATIONS =3D 1 << 5, -}; - -#define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf) -#define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf) -#define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf) -#define NVME_CTRL_CQES_MAX(cqes) (((cqes) >> 4) & 0xf) - -typedef struct NvmeFeatureVal { - uint32_t arbitration; - uint32_t power_mgmt; - uint32_t temp_thresh; - uint32_t err_rec; - uint32_t volatile_wc; - uint32_t num_queues; - uint32_t int_coalescing; - uint32_t *int_vector_config; - uint32_t write_atomicity; - uint32_t async_config; - uint32_t sw_prog_marker; -} NvmeFeatureVal; - -#define NVME_ARB_AB(arb) (arb & 0x7) -#define NVME_ARB_LPW(arb) ((arb >> 8) & 0xff) -#define NVME_ARB_MPW(arb) ((arb >> 16) & 0xff) -#define NVME_ARB_HPW(arb) ((arb >> 24) & 0xff) - -#define NVME_INTC_THR(intc) (intc & 0xff) -#define NVME_INTC_TIME(intc) ((intc >> 8) & 0xff) - -enum NvmeFeatureIds { - NVME_ARBITRATION =3D 0x1, - NVME_POWER_MANAGEMENT =3D 0x2, - NVME_LBA_RANGE_TYPE =3D 0x3, - NVME_TEMPERATURE_THRESHOLD =3D 0x4, - NVME_ERROR_RECOVERY =3D 0x5, - NVME_VOLATILE_WRITE_CACHE =3D 0x6, - NVME_NUMBER_OF_QUEUES =3D 0x7, - NVME_INTERRUPT_COALESCING =3D 0x8, - NVME_INTERRUPT_VECTOR_CONF =3D 0x9, - NVME_WRITE_ATOMICITY =3D 0xa, - NVME_ASYNCHRONOUS_EVENT_CONF =3D 0xb, - NVME_SOFTWARE_PROGRESS_MARKER =3D 0x80 -}; - -typedef struct NvmeRangeType { - uint8_t type; - uint8_t attributes; - uint8_t rsvd2[14]; - uint64_t slba; - uint64_t nlb; - uint8_t guid[16]; - uint8_t rsvd48[16]; -} NvmeRangeType; - -typedef struct NvmeLBAF { - uint16_t ms; - uint8_t ds; - uint8_t rp; -} NvmeLBAF; - -typedef struct NvmeIdNs { - uint64_t nsze; - uint64_t ncap; - uint64_t nuse; - uint8_t nsfeat; - uint8_t nlbaf; - uint8_t flbas; - uint8_t mc; - uint8_t dpc; - uint8_t dps; - uint8_t res30[98]; - NvmeLBAF lbaf[16]; - uint8_t res192[192]; - uint8_t vs[3712]; -} NvmeIdNs; - -#define NVME_ID_NS_NSFEAT_THIN(nsfeat) ((nsfeat & 0x1)) -#define NVME_ID_NS_FLBAS_EXTENDED(flbas) ((flbas >> 4) & 0x1) -#define NVME_ID_NS_FLBAS_INDEX(flbas) ((flbas & 0xf)) -#define NVME_ID_NS_MC_SEPARATE(mc) ((mc >> 1) & 0x1) -#define NVME_ID_NS_MC_EXTENDED(mc) ((mc & 0x1)) -#define NVME_ID_NS_DPC_LAST_EIGHT(dpc) ((dpc >> 4) & 0x1) -#define NVME_ID_NS_DPC_FIRST_EIGHT(dpc) ((dpc >> 3) & 0x1) -#define NVME_ID_NS_DPC_TYPE_3(dpc) ((dpc >> 2) & 0x1) -#define NVME_ID_NS_DPC_TYPE_2(dpc) ((dpc >> 1) & 0x1) -#define NVME_ID_NS_DPC_TYPE_1(dpc) ((dpc & 0x1)) -#define NVME_ID_NS_DPC_TYPE_MASK 0x7 - -enum NvmeIdNsDps { - DPS_TYPE_NONE =3D 0, - DPS_TYPE_1 =3D 1, - DPS_TYPE_2 =3D 2, - DPS_TYPE_3 =3D 3, - DPS_TYPE_MASK =3D 0x7, - DPS_FIRST_EIGHT =3D 8, -}; - -static inline void _nvme_check_size(void) -{ - QEMU_BUILD_BUG_ON(sizeof(NvmeAerResult) !=3D 4); - QEMU_BUILD_BUG_ON(sizeof(NvmeCqe) !=3D 16); - QEMU_BUILD_BUG_ON(sizeof(NvmeDsmRange) !=3D 16); - QEMU_BUILD_BUG_ON(sizeof(NvmeCmd) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeDeleteQ) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeCreateCq) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeCreateSq) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeIdentify) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeRwCmd) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeDsmCmd) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeRangeType) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) !=3D 64); - QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) !=3D 512); - QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) !=3D 512); - QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) !=3D 4096); - QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) !=3D 4096); -} +#include "block/nvme.h" =20 typedef struct NvmeAsyncEvent { QSIMPLEQ_ENTRY(NvmeAsyncEvent) entry; diff --git a/include/block/nvme.h b/include/block/nvme.h new file mode 100644 index 0000000000..849a6f3fa3 --- /dev/null +++ b/include/block/nvme.h @@ -0,0 +1,700 @@ +#ifndef BLOCK_NVME_H +#define BLOCK_NVME_H + +typedef struct NvmeBar { + uint64_t cap; + uint32_t vs; + uint32_t intms; + uint32_t intmc; + uint32_t cc; + uint32_t rsvd1; + uint32_t csts; + uint32_t nssrc; + uint32_t aqa; + uint64_t asq; + uint64_t acq; + uint32_t cmbloc; + uint32_t cmbsz; +} NvmeBar; + +enum NvmeCapShift { + CAP_MQES_SHIFT =3D 0, + CAP_CQR_SHIFT =3D 16, + CAP_AMS_SHIFT =3D 17, + CAP_TO_SHIFT =3D 24, + CAP_DSTRD_SHIFT =3D 32, + CAP_NSSRS_SHIFT =3D 33, + CAP_CSS_SHIFT =3D 37, + CAP_MPSMIN_SHIFT =3D 48, + CAP_MPSMAX_SHIFT =3D 52, +}; + +enum NvmeCapMask { + CAP_MQES_MASK =3D 0xffff, + CAP_CQR_MASK =3D 0x1, + CAP_AMS_MASK =3D 0x3, + CAP_TO_MASK =3D 0xff, + CAP_DSTRD_MASK =3D 0xf, + CAP_NSSRS_MASK =3D 0x1, + CAP_CSS_MASK =3D 0xff, + CAP_MPSMIN_MASK =3D 0xf, + CAP_MPSMAX_MASK =3D 0xf, +}; + +#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK) +#define NVME_CAP_CQR(cap) (((cap) >> CAP_CQR_SHIFT) & CAP_CQR_MASK) +#define NVME_CAP_AMS(cap) (((cap) >> CAP_AMS_SHIFT) & CAP_AMS_MASK) +#define NVME_CAP_TO(cap) (((cap) >> CAP_TO_SHIFT) & CAP_TO_MASK) +#define NVME_CAP_DSTRD(cap) (((cap) >> CAP_DSTRD_SHIFT) & CAP_DSTRD_MASK) +#define NVME_CAP_NSSRS(cap) (((cap) >> CAP_NSSRS_SHIFT) & CAP_NSSRS_MASK) +#define NVME_CAP_CSS(cap) (((cap) >> CAP_CSS_SHIFT) & CAP_CSS_MASK) +#define NVME_CAP_MPSMIN(cap)(((cap) >> CAP_MPSMIN_SHIFT) & CAP_MPSMIN_MASK) +#define NVME_CAP_MPSMAX(cap)(((cap) >> CAP_MPSMAX_SHIFT) & CAP_MPSMAX_MASK) + +#define NVME_CAP_SET_MQES(cap, val) (cap |=3D (uint64_t)(val & CAP_MQES_= MASK) \ + << CAP_MQES_SHI= FT) +#define NVME_CAP_SET_CQR(cap, val) (cap |=3D (uint64_t)(val & CAP_CQR_M= ASK) \ + << CAP_CQR_SHIF= T) +#define NVME_CAP_SET_AMS(cap, val) (cap |=3D (uint64_t)(val & CAP_AMS_M= ASK) \ + << CAP_AMS_SHIF= T) +#define NVME_CAP_SET_TO(cap, val) (cap |=3D (uint64_t)(val & CAP_TO_MA= SK) \ + << CAP_TO_SHIFT) +#define NVME_CAP_SET_DSTRD(cap, val) (cap |=3D (uint64_t)(val & CAP_DSTRD= _MASK) \ + << CAP_DSTRD_SH= IFT) +#define NVME_CAP_SET_NSSRS(cap, val) (cap |=3D (uint64_t)(val & CAP_NSSRS= _MASK) \ + << CAP_NSSRS_SH= IFT) +#define NVME_CAP_SET_CSS(cap, val) (cap |=3D (uint64_t)(val & CAP_CSS_M= ASK) \ + << CAP_CSS_SHIF= T) +#define NVME_CAP_SET_MPSMIN(cap, val) (cap |=3D (uint64_t)(val & CAP_MPSMI= N_MASK)\ + << CAP_MPSMIN_S= HIFT) +#define NVME_CAP_SET_MPSMAX(cap, val) (cap |=3D (uint64_t)(val & CAP_MPSMA= X_MASK)\ + << CAP_MPSMAX_= SHIFT) + +enum NvmeCcShift { + CC_EN_SHIFT =3D 0, + CC_CSS_SHIFT =3D 4, + CC_MPS_SHIFT =3D 7, + CC_AMS_SHIFT =3D 11, + CC_SHN_SHIFT =3D 14, + CC_IOSQES_SHIFT =3D 16, + CC_IOCQES_SHIFT =3D 20, +}; + +enum NvmeCcMask { + CC_EN_MASK =3D 0x1, + CC_CSS_MASK =3D 0x7, + CC_MPS_MASK =3D 0xf, + CC_AMS_MASK =3D 0x7, + CC_SHN_MASK =3D 0x3, + CC_IOSQES_MASK =3D 0xf, + CC_IOCQES_MASK =3D 0xf, +}; + +#define NVME_CC_EN(cc) ((cc >> CC_EN_SHIFT) & CC_EN_MASK) +#define NVME_CC_CSS(cc) ((cc >> CC_CSS_SHIFT) & CC_CSS_MASK) +#define NVME_CC_MPS(cc) ((cc >> CC_MPS_SHIFT) & CC_MPS_MASK) +#define NVME_CC_AMS(cc) ((cc >> CC_AMS_SHIFT) & CC_AMS_MASK) +#define NVME_CC_SHN(cc) ((cc >> CC_SHN_SHIFT) & CC_SHN_MASK) +#define NVME_CC_IOSQES(cc) ((cc >> CC_IOSQES_SHIFT) & CC_IOSQES_MASK) +#define NVME_CC_IOCQES(cc) ((cc >> CC_IOCQES_SHIFT) & CC_IOCQES_MASK) + +enum NvmeCstsShift { + CSTS_RDY_SHIFT =3D 0, + CSTS_CFS_SHIFT =3D 1, + CSTS_SHST_SHIFT =3D 2, + CSTS_NSSRO_SHIFT =3D 4, +}; + +enum NvmeCstsMask { + CSTS_RDY_MASK =3D 0x1, + CSTS_CFS_MASK =3D 0x1, + CSTS_SHST_MASK =3D 0x3, + CSTS_NSSRO_MASK =3D 0x1, +}; + +enum NvmeCsts { + NVME_CSTS_READY =3D 1 << CSTS_RDY_SHIFT, + NVME_CSTS_FAILED =3D 1 << CSTS_CFS_SHIFT, + NVME_CSTS_SHST_NORMAL =3D 0 << CSTS_SHST_SHIFT, + NVME_CSTS_SHST_PROGRESS =3D 1 << CSTS_SHST_SHIFT, + NVME_CSTS_SHST_COMPLETE =3D 2 << CSTS_SHST_SHIFT, + NVME_CSTS_NSSRO =3D 1 << CSTS_NSSRO_SHIFT, +}; + +#define NVME_CSTS_RDY(csts) ((csts >> CSTS_RDY_SHIFT) & CSTS_RDY_MAS= K) +#define NVME_CSTS_CFS(csts) ((csts >> CSTS_CFS_SHIFT) & CSTS_CFS_MAS= K) +#define NVME_CSTS_SHST(csts) ((csts >> CSTS_SHST_SHIFT) & CSTS_SHST_MA= SK) +#define NVME_CSTS_NSSRO(csts) ((csts >> CSTS_NSSRO_SHIFT) & CSTS_NSSRO_M= ASK) + +enum NvmeAqaShift { + AQA_ASQS_SHIFT =3D 0, + AQA_ACQS_SHIFT =3D 16, +}; + +enum NvmeAqaMask { + AQA_ASQS_MASK =3D 0xfff, + AQA_ACQS_MASK =3D 0xfff, +}; + +#define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK) +#define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK) + +enum NvmeCmblocShift { + CMBLOC_BIR_SHIFT =3D 0, + CMBLOC_OFST_SHIFT =3D 12, +}; + +enum NvmeCmblocMask { + CMBLOC_BIR_MASK =3D 0x7, + CMBLOC_OFST_MASK =3D 0xfffff, +}; + +#define NVME_CMBLOC_BIR(cmbloc) ((cmbloc >> CMBLOC_BIR_SHIFT) & \ + CMBLOC_BIR_MASK) +#define NVME_CMBLOC_OFST(cmbloc)((cmbloc >> CMBLOC_OFST_SHIFT) & \ + CMBLOC_OFST_MASK) + +#define NVME_CMBLOC_SET_BIR(cmbloc, val) \ + (cmbloc |=3D (uint64_t)(val & CMBLOC_BIR_MASK) << CMBLOC_BIR_SHIFT) +#define NVME_CMBLOC_SET_OFST(cmbloc, val) \ + (cmbloc |=3D (uint64_t)(val & CMBLOC_OFST_MASK) << CMBLOC_OFST_SHIFT) + +enum NvmeCmbszShift { + CMBSZ_SQS_SHIFT =3D 0, + CMBSZ_CQS_SHIFT =3D 1, + CMBSZ_LISTS_SHIFT =3D 2, + CMBSZ_RDS_SHIFT =3D 3, + CMBSZ_WDS_SHIFT =3D 4, + CMBSZ_SZU_SHIFT =3D 8, + CMBSZ_SZ_SHIFT =3D 12, +}; + +enum NvmeCmbszMask { + CMBSZ_SQS_MASK =3D 0x1, + CMBSZ_CQS_MASK =3D 0x1, + CMBSZ_LISTS_MASK =3D 0x1, + CMBSZ_RDS_MASK =3D 0x1, + CMBSZ_WDS_MASK =3D 0x1, + CMBSZ_SZU_MASK =3D 0xf, + CMBSZ_SZ_MASK =3D 0xfffff, +}; + +#define NVME_CMBSZ_SQS(cmbsz) ((cmbsz >> CMBSZ_SQS_SHIFT) & CMBSZ_SQS_M= ASK) +#define NVME_CMBSZ_CQS(cmbsz) ((cmbsz >> CMBSZ_CQS_SHIFT) & CMBSZ_CQS_M= ASK) +#define NVME_CMBSZ_LISTS(cmbsz)((cmbsz >> CMBSZ_LISTS_SHIFT) & CMBSZ_LISTS= _MASK) +#define NVME_CMBSZ_RDS(cmbsz) ((cmbsz >> CMBSZ_RDS_SHIFT) & CMBSZ_RDS_M= ASK) +#define NVME_CMBSZ_WDS(cmbsz) ((cmbsz >> CMBSZ_WDS_SHIFT) & CMBSZ_WDS_M= ASK) +#define NVME_CMBSZ_SZU(cmbsz) ((cmbsz >> CMBSZ_SZU_SHIFT) & CMBSZ_SZU_M= ASK) +#define NVME_CMBSZ_SZ(cmbsz) ((cmbsz >> CMBSZ_SZ_SHIFT) & CMBSZ_SZ_MA= SK) + +#define NVME_CMBSZ_SET_SQS(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_SQS_MASK) << CMBSZ_SQS_SHIFT) +#define NVME_CMBSZ_SET_CQS(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_CQS_MASK) << CMBSZ_CQS_SHIFT) +#define NVME_CMBSZ_SET_LISTS(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_LISTS_MASK) << CMBSZ_LISTS_SHIFT) +#define NVME_CMBSZ_SET_RDS(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_RDS_MASK) << CMBSZ_RDS_SHIFT) +#define NVME_CMBSZ_SET_WDS(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_WDS_MASK) << CMBSZ_WDS_SHIFT) +#define NVME_CMBSZ_SET_SZU(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_SZU_MASK) << CMBSZ_SZU_SHIFT) +#define NVME_CMBSZ_SET_SZ(cmbsz, val) \ + (cmbsz |=3D (uint64_t)(val & CMBSZ_SZ_MASK) << CMBSZ_SZ_SHIFT) + +#define NVME_CMBSZ_GETSIZE(cmbsz) \ + (NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz)))) + +typedef struct NvmeCmd { + uint8_t opcode; + uint8_t fuse; + uint16_t cid; + uint32_t nsid; + uint64_t res1; + uint64_t mptr; + uint64_t prp1; + uint64_t prp2; + uint32_t cdw10; + uint32_t cdw11; + uint32_t cdw12; + uint32_t cdw13; + uint32_t cdw14; + uint32_t cdw15; +} NvmeCmd; + +enum NvmeAdminCommands { + NVME_ADM_CMD_DELETE_SQ =3D 0x00, + NVME_ADM_CMD_CREATE_SQ =3D 0x01, + NVME_ADM_CMD_GET_LOG_PAGE =3D 0x02, + NVME_ADM_CMD_DELETE_CQ =3D 0x04, + NVME_ADM_CMD_CREATE_CQ =3D 0x05, + NVME_ADM_CMD_IDENTIFY =3D 0x06, + NVME_ADM_CMD_ABORT =3D 0x08, + NVME_ADM_CMD_SET_FEATURES =3D 0x09, + NVME_ADM_CMD_GET_FEATURES =3D 0x0a, + NVME_ADM_CMD_ASYNC_EV_REQ =3D 0x0c, + NVME_ADM_CMD_ACTIVATE_FW =3D 0x10, + NVME_ADM_CMD_DOWNLOAD_FW =3D 0x11, + NVME_ADM_CMD_FORMAT_NVM =3D 0x80, + NVME_ADM_CMD_SECURITY_SEND =3D 0x81, + NVME_ADM_CMD_SECURITY_RECV =3D 0x82, +}; + +enum NvmeIoCommands { + NVME_CMD_FLUSH =3D 0x00, + NVME_CMD_WRITE =3D 0x01, + NVME_CMD_READ =3D 0x02, + NVME_CMD_WRITE_UNCOR =3D 0x04, + NVME_CMD_COMPARE =3D 0x05, + NVME_CMD_WRITE_ZEROS =3D 0x08, + NVME_CMD_DSM =3D 0x09, +}; + +typedef struct NvmeDeleteQ { + uint8_t opcode; + uint8_t flags; + uint16_t cid; + uint32_t rsvd1[9]; + uint16_t qid; + uint16_t rsvd10; + uint32_t rsvd11[5]; +} NvmeDeleteQ; + +typedef struct NvmeCreateCq { + uint8_t opcode; + uint8_t flags; + uint16_t cid; + uint32_t rsvd1[5]; + uint64_t prp1; + uint64_t rsvd8; + uint16_t cqid; + uint16_t qsize; + uint16_t cq_flags; + uint16_t irq_vector; + uint32_t rsvd12[4]; +} NvmeCreateCq; + +#define NVME_CQ_FLAGS_PC(cq_flags) (cq_flags & 0x1) +#define NVME_CQ_FLAGS_IEN(cq_flags) ((cq_flags >> 1) & 0x1) + +typedef struct NvmeCreateSq { + uint8_t opcode; + uint8_t flags; + uint16_t cid; + uint32_t rsvd1[5]; + uint64_t prp1; + uint64_t rsvd8; + uint16_t sqid; + uint16_t qsize; + uint16_t sq_flags; + uint16_t cqid; + uint32_t rsvd12[4]; +} NvmeCreateSq; + +#define NVME_SQ_FLAGS_PC(sq_flags) (sq_flags & 0x1) +#define NVME_SQ_FLAGS_QPRIO(sq_flags) ((sq_flags >> 1) & 0x3) + +enum NvmeQueueFlags { + NVME_Q_PC =3D 1, + NVME_Q_PRIO_URGENT =3D 0, + NVME_Q_PRIO_HIGH =3D 1, + NVME_Q_PRIO_NORMAL =3D 2, + NVME_Q_PRIO_LOW =3D 3, +}; + +typedef struct NvmeIdentify { + uint8_t opcode; + uint8_t flags; + uint16_t cid; + uint32_t nsid; + uint64_t rsvd2[2]; + uint64_t prp1; + uint64_t prp2; + uint32_t cns; + uint32_t rsvd11[5]; +} NvmeIdentify; + +typedef struct NvmeRwCmd { + uint8_t opcode; + uint8_t flags; + uint16_t cid; + uint32_t nsid; + uint64_t rsvd2; + uint64_t mptr; + uint64_t prp1; + uint64_t prp2; + uint64_t slba; + uint16_t nlb; + uint16_t control; + uint32_t dsmgmt; + uint32_t reftag; + uint16_t apptag; + uint16_t appmask; +} NvmeRwCmd; + +enum { + NVME_RW_LR =3D 1 << 15, + NVME_RW_FUA =3D 1 << 14, + NVME_RW_DSM_FREQ_UNSPEC =3D 0, + NVME_RW_DSM_FREQ_TYPICAL =3D 1, + NVME_RW_DSM_FREQ_RARE =3D 2, + NVME_RW_DSM_FREQ_READS =3D 3, + NVME_RW_DSM_FREQ_WRITES =3D 4, + NVME_RW_DSM_FREQ_RW =3D 5, + NVME_RW_DSM_FREQ_ONCE =3D 6, + NVME_RW_DSM_FREQ_PREFETCH =3D 7, + NVME_RW_DSM_FREQ_TEMP =3D 8, + NVME_RW_DSM_LATENCY_NONE =3D 0 << 4, + NVME_RW_DSM_LATENCY_IDLE =3D 1 << 4, + NVME_RW_DSM_LATENCY_NORM =3D 2 << 4, + NVME_RW_DSM_LATENCY_LOW =3D 3 << 4, + NVME_RW_DSM_SEQ_REQ =3D 1 << 6, + NVME_RW_DSM_COMPRESSED =3D 1 << 7, + NVME_RW_PRINFO_PRACT =3D 1 << 13, + NVME_RW_PRINFO_PRCHK_GUARD =3D 1 << 12, + NVME_RW_PRINFO_PRCHK_APP =3D 1 << 11, + NVME_RW_PRINFO_PRCHK_REF =3D 1 << 10, +}; + +typedef struct NvmeDsmCmd { + uint8_t opcode; + uint8_t flags; + uint16_t cid; + uint32_t nsid; + uint64_t rsvd2[2]; + uint64_t prp1; + uint64_t prp2; + uint32_t nr; + uint32_t attributes; + uint32_t rsvd12[4]; +} NvmeDsmCmd; + +enum { + NVME_DSMGMT_IDR =3D 1 << 0, + NVME_DSMGMT_IDW =3D 1 << 1, + NVME_DSMGMT_AD =3D 1 << 2, +}; + +typedef struct NvmeDsmRange { + uint32_t cattr; + uint32_t nlb; + uint64_t slba; +} NvmeDsmRange; + +enum NvmeAsyncEventRequest { + NVME_AER_TYPE_ERROR =3D 0, + NVME_AER_TYPE_SMART =3D 1, + NVME_AER_TYPE_IO_SPECIFIC =3D 6, + NVME_AER_TYPE_VENDOR_SPECIFIC =3D 7, + NVME_AER_INFO_ERR_INVALID_SQ =3D 0, + NVME_AER_INFO_ERR_INVALID_DB =3D 1, + NVME_AER_INFO_ERR_DIAG_FAIL =3D 2, + NVME_AER_INFO_ERR_PERS_INTERNAL_ERR =3D 3, + NVME_AER_INFO_ERR_TRANS_INTERNAL_ERR =3D 4, + NVME_AER_INFO_ERR_FW_IMG_LOAD_ERR =3D 5, + NVME_AER_INFO_SMART_RELIABILITY =3D 0, + NVME_AER_INFO_SMART_TEMP_THRESH =3D 1, + NVME_AER_INFO_SMART_SPARE_THRESH =3D 2, +}; + +typedef struct NvmeAerResult { + uint8_t event_type; + uint8_t event_info; + uint8_t log_page; + uint8_t resv; +} NvmeAerResult; + +typedef struct NvmeCqe { + uint32_t result; + uint32_t rsvd; + uint16_t sq_head; + uint16_t sq_id; + uint16_t cid; + uint16_t status; +} NvmeCqe; + +enum NvmeStatusCodes { + NVME_SUCCESS =3D 0x0000, + NVME_INVALID_OPCODE =3D 0x0001, + NVME_INVALID_FIELD =3D 0x0002, + NVME_CID_CONFLICT =3D 0x0003, + NVME_DATA_TRAS_ERROR =3D 0x0004, + NVME_POWER_LOSS_ABORT =3D 0x0005, + NVME_INTERNAL_DEV_ERROR =3D 0x0006, + NVME_CMD_ABORT_REQ =3D 0x0007, + NVME_CMD_ABORT_SQ_DEL =3D 0x0008, + NVME_CMD_ABORT_FAILED_FUSE =3D 0x0009, + NVME_CMD_ABORT_MISSING_FUSE =3D 0x000a, + NVME_INVALID_NSID =3D 0x000b, + NVME_CMD_SEQ_ERROR =3D 0x000c, + NVME_LBA_RANGE =3D 0x0080, + NVME_CAP_EXCEEDED =3D 0x0081, + NVME_NS_NOT_READY =3D 0x0082, + NVME_NS_RESV_CONFLICT =3D 0x0083, + NVME_INVALID_CQID =3D 0x0100, + NVME_INVALID_QID =3D 0x0101, + NVME_MAX_QSIZE_EXCEEDED =3D 0x0102, + NVME_ACL_EXCEEDED =3D 0x0103, + NVME_RESERVED =3D 0x0104, + NVME_AER_LIMIT_EXCEEDED =3D 0x0105, + NVME_INVALID_FW_SLOT =3D 0x0106, + NVME_INVALID_FW_IMAGE =3D 0x0107, + NVME_INVALID_IRQ_VECTOR =3D 0x0108, + NVME_INVALID_LOG_ID =3D 0x0109, + NVME_INVALID_FORMAT =3D 0x010a, + NVME_FW_REQ_RESET =3D 0x010b, + NVME_INVALID_QUEUE_DEL =3D 0x010c, + NVME_FID_NOT_SAVEABLE =3D 0x010d, + NVME_FID_NOT_NSID_SPEC =3D 0x010f, + NVME_FW_REQ_SUSYSTEM_RESET =3D 0x0110, + NVME_CONFLICTING_ATTRS =3D 0x0180, + NVME_INVALID_PROT_INFO =3D 0x0181, + NVME_WRITE_TO_RO =3D 0x0182, + NVME_WRITE_FAULT =3D 0x0280, + NVME_UNRECOVERED_READ =3D 0x0281, + NVME_E2E_GUARD_ERROR =3D 0x0282, + NVME_E2E_APP_ERROR =3D 0x0283, + NVME_E2E_REF_ERROR =3D 0x0284, + NVME_CMP_FAILURE =3D 0x0285, + NVME_ACCESS_DENIED =3D 0x0286, + NVME_MORE =3D 0x2000, + NVME_DNR =3D 0x4000, + NVME_NO_COMPLETE =3D 0xffff, +}; + +typedef struct NvmeFwSlotInfoLog { + uint8_t afi; + uint8_t reserved1[7]; + uint8_t frs1[8]; + uint8_t frs2[8]; + uint8_t frs3[8]; + uint8_t frs4[8]; + uint8_t frs5[8]; + uint8_t frs6[8]; + uint8_t frs7[8]; + uint8_t reserved2[448]; +} NvmeFwSlotInfoLog; + +typedef struct NvmeErrorLog { + uint64_t error_count; + uint16_t sqid; + uint16_t cid; + uint16_t status_field; + uint16_t param_error_location; + uint64_t lba; + uint32_t nsid; + uint8_t vs; + uint8_t resv[35]; +} NvmeErrorLog; + +typedef struct NvmeSmartLog { + uint8_t critical_warning; + uint8_t temperature[2]; + uint8_t available_spare; + uint8_t available_spare_threshold; + uint8_t percentage_used; + uint8_t reserved1[26]; + uint64_t data_units_read[2]; + uint64_t data_units_written[2]; + uint64_t host_read_commands[2]; + uint64_t host_write_commands[2]; + uint64_t controller_busy_time[2]; + uint64_t power_cycles[2]; + uint64_t power_on_hours[2]; + uint64_t unsafe_shutdowns[2]; + uint64_t media_errors[2]; + uint64_t number_of_error_log_entries[2]; + uint8_t reserved2[320]; +} NvmeSmartLog; + +enum NvmeSmartWarn { + NVME_SMART_SPARE =3D 1 << 0, + NVME_SMART_TEMPERATURE =3D 1 << 1, + NVME_SMART_RELIABILITY =3D 1 << 2, + NVME_SMART_MEDIA_READ_ONLY =3D 1 << 3, + NVME_SMART_FAILED_VOLATILE_MEDIA =3D 1 << 4, +}; + +enum LogIdentifier { + NVME_LOG_ERROR_INFO =3D 0x01, + NVME_LOG_SMART_INFO =3D 0x02, + NVME_LOG_FW_SLOT_INFO =3D 0x03, +}; + +typedef struct NvmePSD { + uint16_t mp; + uint16_t reserved; + uint32_t enlat; + uint32_t exlat; + uint8_t rrt; + uint8_t rrl; + uint8_t rwt; + uint8_t rwl; + uint8_t resv[16]; +} NvmePSD; + +typedef struct NvmeIdCtrl { + uint16_t vid; + uint16_t ssvid; + uint8_t sn[20]; + uint8_t mn[40]; + uint8_t fr[8]; + uint8_t rab; + uint8_t ieee[3]; + uint8_t cmic; + uint8_t mdts; + uint8_t rsvd255[178]; + uint16_t oacs; + uint8_t acl; + uint8_t aerl; + uint8_t frmw; + uint8_t lpa; + uint8_t elpe; + uint8_t npss; + uint8_t rsvd511[248]; + uint8_t sqes; + uint8_t cqes; + uint16_t rsvd515; + uint32_t nn; + uint16_t oncs; + uint16_t fuses; + uint8_t fna; + uint8_t vwc; + uint16_t awun; + uint16_t awupf; + uint8_t rsvd703[174]; + uint8_t rsvd2047[1344]; + NvmePSD psd[32]; + uint8_t vs[1024]; +} NvmeIdCtrl; + +enum NvmeIdCtrlOacs { + NVME_OACS_SECURITY =3D 1 << 0, + NVME_OACS_FORMAT =3D 1 << 1, + NVME_OACS_FW =3D 1 << 2, +}; + +enum NvmeIdCtrlOncs { + NVME_ONCS_COMPARE =3D 1 << 0, + NVME_ONCS_WRITE_UNCORR =3D 1 << 1, + NVME_ONCS_DSM =3D 1 << 2, + NVME_ONCS_WRITE_ZEROS =3D 1 << 3, + NVME_ONCS_FEATURES =3D 1 << 4, + NVME_ONCS_RESRVATIONS =3D 1 << 5, +}; + +#define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf) +#define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf) +#define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf) +#define NVME_CTRL_CQES_MAX(cqes) (((cqes) >> 4) & 0xf) + +typedef struct NvmeFeatureVal { + uint32_t arbitration; + uint32_t power_mgmt; + uint32_t temp_thresh; + uint32_t err_rec; + uint32_t volatile_wc; + uint32_t num_queues; + uint32_t int_coalescing; + uint32_t *int_vector_config; + uint32_t write_atomicity; + uint32_t async_config; + uint32_t sw_prog_marker; +} NvmeFeatureVal; + +#define NVME_ARB_AB(arb) (arb & 0x7) +#define NVME_ARB_LPW(arb) ((arb >> 8) & 0xff) +#define NVME_ARB_MPW(arb) ((arb >> 16) & 0xff) +#define NVME_ARB_HPW(arb) ((arb >> 24) & 0xff) + +#define NVME_INTC_THR(intc) (intc & 0xff) +#define NVME_INTC_TIME(intc) ((intc >> 8) & 0xff) + +enum NvmeFeatureIds { + NVME_ARBITRATION =3D 0x1, + NVME_POWER_MANAGEMENT =3D 0x2, + NVME_LBA_RANGE_TYPE =3D 0x3, + NVME_TEMPERATURE_THRESHOLD =3D 0x4, + NVME_ERROR_RECOVERY =3D 0x5, + NVME_VOLATILE_WRITE_CACHE =3D 0x6, + NVME_NUMBER_OF_QUEUES =3D 0x7, + NVME_INTERRUPT_COALESCING =3D 0x8, + NVME_INTERRUPT_VECTOR_CONF =3D 0x9, + NVME_WRITE_ATOMICITY =3D 0xa, + NVME_ASYNCHRONOUS_EVENT_CONF =3D 0xb, + NVME_SOFTWARE_PROGRESS_MARKER =3D 0x80 +}; + +typedef struct NvmeRangeType { + uint8_t type; + uint8_t attributes; + uint8_t rsvd2[14]; + uint64_t slba; + uint64_t nlb; + uint8_t guid[16]; + uint8_t rsvd48[16]; +} NvmeRangeType; + +typedef struct NvmeLBAF { + uint16_t ms; + uint8_t ds; + uint8_t rp; +} NvmeLBAF; + +typedef struct NvmeIdNs { + uint64_t nsze; + uint64_t ncap; + uint64_t nuse; + uint8_t nsfeat; + uint8_t nlbaf; + uint8_t flbas; + uint8_t mc; + uint8_t dpc; + uint8_t dps; + uint8_t res30[98]; + NvmeLBAF lbaf[16]; + uint8_t res192[192]; + uint8_t vs[3712]; +} NvmeIdNs; + +#define NVME_ID_NS_NSFEAT_THIN(nsfeat) ((nsfeat & 0x1)) +#define NVME_ID_NS_FLBAS_EXTENDED(flbas) ((flbas >> 4) & 0x1) +#define NVME_ID_NS_FLBAS_INDEX(flbas) ((flbas & 0xf)) +#define NVME_ID_NS_MC_SEPARATE(mc) ((mc >> 1) & 0x1) +#define NVME_ID_NS_MC_EXTENDED(mc) ((mc & 0x1)) +#define NVME_ID_NS_DPC_LAST_EIGHT(dpc) ((dpc >> 4) & 0x1) +#define NVME_ID_NS_DPC_FIRST_EIGHT(dpc) ((dpc >> 3) & 0x1) +#define NVME_ID_NS_DPC_TYPE_3(dpc) ((dpc >> 2) & 0x1) +#define NVME_ID_NS_DPC_TYPE_2(dpc) ((dpc >> 1) & 0x1) +#define NVME_ID_NS_DPC_TYPE_1(dpc) ((dpc & 0x1)) +#define NVME_ID_NS_DPC_TYPE_MASK 0x7 + +enum NvmeIdNsDps { + DPS_TYPE_NONE =3D 0, + DPS_TYPE_1 =3D 1, + DPS_TYPE_2 =3D 2, + DPS_TYPE_3 =3D 3, + DPS_TYPE_MASK =3D 0x7, + DPS_FIRST_EIGHT =3D 8, +}; + +static inline void _nvme_check_size(void) +{ + QEMU_BUILD_BUG_ON(sizeof(NvmeAerResult) !=3D 4); + QEMU_BUILD_BUG_ON(sizeof(NvmeCqe) !=3D 16); + QEMU_BUILD_BUG_ON(sizeof(NvmeDsmRange) !=3D 16); + QEMU_BUILD_BUG_ON(sizeof(NvmeCmd) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeDeleteQ) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeCreateCq) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeCreateSq) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeIdentify) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeRwCmd) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeDsmCmd) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeRangeType) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) !=3D 64); + QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) !=3D 512); + QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) !=3D 512); + QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) !=3D 4096); + QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) !=3D 4096); +} +#endif --=20 2.14.3