[1/3] hw/block/nvme: add NVMe 1.4 specific fields
diff mbox series

Message ID 20200630043122.1307043-2-its@irrelevant.dk
State New
Headers show
Series
  • hw/block/nvme: bump to v1.4
Related show

Commit Message

Klaus Jensen June 30, 2020, 4:31 a.m. UTC
From: Klaus Jensen <k.jensen@samsung.com>

Add new fields from NVM Express v1.4.

Signed-off-by: Klaus Jensen <klaus.jensen@cnexlabs.com>
---
 hw/block/nvme.c      |   3 +-
 include/block/nvme.h | 195 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 172 insertions(+), 26 deletions(-)

Comments

Philippe Mathieu-Daudé June 30, 2020, 9:38 a.m. UTC | #1
On 6/30/20 6:31 AM, Klaus Jensen wrote:
> From: Klaus Jensen <k.jensen@samsung.com>
> 
> Add new fields from NVM Express v1.4.
> 
> Signed-off-by: Klaus Jensen <klaus.jensen@cnexlabs.com>
> ---
>  hw/block/nvme.c      |   3 +-
>  include/block/nvme.h | 195 +++++++++++++++++++++++++++++++++++++------
>  2 files changed, 172 insertions(+), 26 deletions(-)
> 
> diff --git a/hw/block/nvme.c b/hw/block/nvme.c
> index 8e147b667c81..07ac409f37c9 100644
> --- a/hw/block/nvme.c
> +++ b/hw/block/nvme.c
> @@ -60,7 +60,7 @@
>  #define NVME_MAX_IOQPAIRS 0xffff
>  #define NVME_REG_SIZE 0x1000
>  #define NVME_DB_SIZE  4
> -#define NVME_SPEC_VER 0x00010300
> +#define NVME_SPEC_VER 0x00010400
>  #define NVME_CMB_BIR 2
>  #define NVME_PMR_BIR 2
>  #define NVME_TEMPERATURE 0x143
> @@ -2910,6 +2910,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
>      id->ieee[2] = 0xb3;
>      id->mdts = n->params.mdts;
>      id->ver = cpu_to_le32(NVME_SPEC_VER);
> +    id->cntrltype = 0x1;
>      id->oacs = cpu_to_le16(0);
>  
>      /*
> diff --git a/include/block/nvme.h b/include/block/nvme.h
> index 2a9c5e95bfd2..b27be237cd33 100644
> --- a/include/block/nvme.h
> +++ b/include/block/nvme.h
> @@ -7,7 +7,7 @@ typedef struct NvmeBar {
>      uint32_t    intms;
>      uint32_t    intmc;
>      uint32_t    cc;
> -    uint32_t    rsvd1;
> +    uint8_t     rsvd24[4];
>      uint32_t    csts;
>      uint32_t    nssrc;
>      uint32_t    aqa;
> @@ -15,14 +15,20 @@ typedef struct NvmeBar {
>      uint64_t    acq;
>      uint32_t    cmbloc;
>      uint32_t    cmbsz;
> -    uint8_t     padding[3520]; /* not used by QEMU */
> +    uint32_t    bpinfo;
> +    uint32_t    bprsel;
> +    uint64_t    bpmbl;
> +    uint64_t    cmbmsc;
> +    uint32_t    cmbsts;
> +    uint8_t     rsvd92[3492];
>      uint32_t    pmrcap;
>      uint32_t    pmrctl;
>      uint32_t    pmrsts;
>      uint32_t    pmrebs;
>      uint32_t    pmrswtp;
> -    uint32_t    pmrmsc;
> -} NvmeBar;
> +    uint64_t    pmrmsc;
> +    uint8_t     rsvd3612[484];
> +} QEMU_PACKED NvmeBar;
>  
>  enum NvmeCapShift {
>      CAP_MQES_SHIFT     = 0,
> @@ -34,7 +40,8 @@ enum NvmeCapShift {
>      CAP_CSS_SHIFT      = 37,
>      CAP_MPSMIN_SHIFT   = 48,
>      CAP_MPSMAX_SHIFT   = 52,
> -    CAP_PMR_SHIFT      = 56,
> +    CAP_PMRS_SHIFT     = 56,
> +    CAP_CMBS_SHIFT     = 57,
>  };
>  
>  enum NvmeCapMask {
> @@ -47,7 +54,8 @@ enum NvmeCapMask {
>      CAP_CSS_MASK       = 0xff,
>      CAP_MPSMIN_MASK    = 0xf,
>      CAP_MPSMAX_MASK    = 0xf,
> -    CAP_PMR_MASK       = 0x1,
> +    CAP_PMRS_MASK      = 0x1,
> +    CAP_CMBS_MASK      = 0x1,
>  };
>  
>  #define NVME_CAP_MQES(cap)  (((cap) >> CAP_MQES_SHIFT)   & CAP_MQES_MASK)
> @@ -59,6 +67,8 @@ enum NvmeCapMask {
>  #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_PMRS(cap)  (((cap) >> CAP_PMRS_SHIFT)   & CAP_PMRS_MASK)
> +#define NVME_CAP_CMBS(cap)  (((cap) >> CAP_CMBS_SHIFT)   & CAP_CMBS_MASK)
>  
>  #define NVME_CAP_SET_MQES(cap, val)   (cap |= (uint64_t)(val & CAP_MQES_MASK)  \
>                                                             << CAP_MQES_SHIFT)
> @@ -78,8 +88,10 @@ enum NvmeCapMask {
>                                                             << CAP_MPSMIN_SHIFT)
>  #define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
>                                                              << CAP_MPSMAX_SHIFT)
> -#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
> -                                                            << CAP_PMR_SHIFT)
> +#define NVME_CAP_SET_PMRS(cap, val)   (cap |= (uint64_t)(val & CAP_PMRS_MASK)\
> +                                                            << CAP_PMRS_SHIFT)
> +#define NVME_CAP_SET_CMBS(cap, val)   (cap |= (uint64_t)(val & CAP_CMBS_MASK)\
> +                                                            << CAP_CMBS_SHIFT)
>  
>  enum NvmeCcShift {
>      CC_EN_SHIFT     = 0,
> @@ -151,22 +163,58 @@ enum NvmeAqaMask {
>  #define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK)
>  
>  enum NvmeCmblocShift {
> -    CMBLOC_BIR_SHIFT  = 0,
> -    CMBLOC_OFST_SHIFT = 12,
> +    CMBLOC_BIR_SHIFT     = 0,
> +    CMBLOC_CQMMS_SHIFT   = 3,
> +    CMBLOC_CQPDS_SHIFT   = 4,
> +    CMBLOC_CDPMLS_SHIFT  = 5,
> +    CMBLOC_CDPCILS_SHIFT = 6,
> +    CMBLOC_CDMMMS_SHIFT  = 7,
> +    CMBLOC_CQDA_SHIFT    = 8,
> +    CMBLOC_OFST_SHIFT    = 12,
>  };
>  
>  enum NvmeCmblocMask {
> -    CMBLOC_BIR_MASK  = 0x7,
> -    CMBLOC_OFST_MASK = 0xfffff,
> +    CMBLOC_BIR_MASK     = 0x7,
> +    CMBLOC_CQMMS_MASK   = 0x1,
> +    CMBLOC_CQPDS_MASK   = 0x1,
> +    CMBLOC_CDPMLS_MASK  = 0x1,
> +    CMBLOC_CDPCILS_MASK = 0x1,
> +    CMBLOC_CDMMMS_MASK  = 0x1,
> +    CMBLOC_CQDA_MASK    = 0x1,
> +    CMBLOC_OFST_MASK    = 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_BIR(cmbloc) \
> +    ((cmbloc >> CMBLOC_BIR_SHIFT) & CMBLOC_BIR_MASK)
> +#define NVME_CMBLOC_CQMMS(cmbloc) \
> +    ((cmbloc >> CMBLOC_CQMMS_SHIFT) & CMBLOC_CQMMS_MASK)
> +#define NVME_CMBLOC_CQPDS(cmbloc) \
> +    ((cmbloc >> CMBLOC_CQPDS_SHIFT) & CMBLOC_CQPDS_MASK)
> +#define NVME_CMBLOC_CDPMLS(cmbloc) \
> +    ((cmbloc >> CMBLOC_CDPMLS_SHIFT) & CMBLOC_CDPMLS_MASK)
> +#define NVME_CMBLOC_CDPCILS(cmbloc) \
> +    ((cmbloc >> CMBLOC_CDPCILS_SHIFT) & CMBLOC_CDPCILS_MASK)
> +#define NVME_CMBLOC_CDMMS(cmbloc) \
> +    ((cmbloc >> CMBLOC_CDMMS_SHIFT) & CMBLOC_CDMMS_MASK)
> +#define NVME_CMBLOC_CQDA(cmbloc) \
> +    ((cmbloc >> CMBLOC_CQDA_SHIFT) & CMBLOC_CQDA_MASK)
> +#define NVME_CMBLOC_OFST(cmbloc) \
> +    ((cmbloc >> CMBLOC_OFST_SHIFT) & CMBLOC_OFST_MASK)
>  
> -#define NVME_CMBLOC_SET_BIR(cmbloc, val)  \
> +#define NVME_CMBLOC_SET_BIR(cmbloc, val) \
>      (cmbloc |= (uint64_t)(val & CMBLOC_BIR_MASK) << CMBLOC_BIR_SHIFT)
> +#define NVME_CMBLOC_SET_CQMMS(cmbloc, val) \
> +    (cmbloc |= (uint64_t)(val & CMBLOC_CQMMS_MASK) << CMBLOC_CQMMS_SHIFT)
> +#define NVME_CMBLOC_SET_CQPDS(cmbloc, val) \
> +    (cmbloc |= (uint64_t)(val & CMBLOC_CQPDS_MASK) << CMBLOC_CQPDS_SHIFT)
> +#define NVME_CMBLOC_SET_CDPMLS(cmbloc, val) \
> +    (cmbloc |= (uint64_t)(val & CMBLOC_CDPMLS_MASK) << CMBLOC_CDPMLS_SHIFT)
> +#define NVME_CMBLOC_SET_CDPCILS(cmbloc, val) \
> +    (cmbloc |= (uint64_t)(val & CMBLOC_CDPCILS_MASK) << CMBLOC_CDPCILS_SHIFT)
> +#define NVME_CMBLOC_SET_CDMMS(cmbloc, val) \
> +    (cmbloc |= (uint64_t)(val & CMBLOC_CDMMS_MASK) << CMBLOC_CDMMS_SHIFT)
> +#define NVME_CMBLOC_SET_CQDA(cmbloc, val) \
> +    (cmbloc |= (uint64_t)(val & CMBLOC_CQDA_MASK) << CMBLOC_CQDA_SHIFT)
>  #define NVME_CMBLOC_SET_OFST(cmbloc, val) \
>      (cmbloc |= (uint64_t)(val & CMBLOC_OFST_MASK) << CMBLOC_OFST_SHIFT)
>  
> @@ -377,6 +425,35 @@ enum NvmePmrmscMask {
>  #define NVME_PMRMSC_SET_CBA(pmrmsc, val)   \
>      (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
>  
> +enum NvmeCmbmscShift {
> +    CMBMSC_CRE_SHIFT  = 0,
> +    CMBMSC_CMSE_SHIFT = 1,
> +    CMBMSC_CBA_SHIFT  = 12,
> +};
> +
> +enum NvmeCmbmscMask {
> +    CMBMSC_CRE_MASK  = 0x1,
> +    CMBMSC_CMSE_MASK = 0x1,
> +};
> +
> +#define CMBMSC_CBA_MASK ((1 << 52) - 1)
> +
> +#define NVME_CMBMSC_CRE(cmbmsc) \
> +    ((cmbmsc >> CMBMSC_CRE_SHIFT)  & CMBMSC_CRE_MASK)
> +#define NVME_CMBMSC_CMSE(cmbmsc) \
> +    ((cmbmsc >> CMBMSC_CMSE_SHIFT) & CMBMSC_CMSE_MASK)
> +#define NVME_CMBMSC_CBA(cmbmsc) \
> +    ((cmbmsc >> CMBMSC_CBA_SHIFT)  & CMBMSC_CBA_MASK)
> +
> +#define NVME_CMBMSC_SET_CRE(cmbmsc, val)  \
> +    (cmbmsc |= (uint64_t)(val & CMBMSC_CRE_MASK) << CMBMSC_CRE_SHIFT)
> +#define NVME_CMBMSC_SET_CMSE(cmbmsc, val) \
> +    (cmbmsc |= (uint64_t)(val & CMBMSC_CMSE_MASK) << CMBMSC_CMSE_SHIFT)
> +#define NVME_CMBMSC_SET_CBA(cmbmsc, val)  \
> +    (cmbmsc |= (uint64_t)(val & CMBMSC_CBA_MASK) << CMBMSC_CBA_SHIFT)
> +
> +#define NVME_CMBSTS_CBAI(cmbsts) (cmsts & 0x1)
> +
>  enum NvmeSglDescriptorType {
>      NVME_SGL_DESCR_TYPE_DATA_BLOCK          = 0x0,
>      NVME_SGL_DESCR_TYPE_BIT_BUCKET          = 0x1,
> @@ -523,8 +600,12 @@ typedef struct NvmeIdentify {
>      uint64_t    rsvd2[2];
>      uint64_t    prp1;
>      uint64_t    prp2;
> -    uint32_t    cns;
> -    uint32_t    rsvd11[5];
> +    uint8_t     cns;
> +    uint8_t     rsvd3;
> +    uint16_t    cntid;
> +    uint16_t    nvmsetid;
> +    uint16_t    rsvd4;
> +    uint32_t    rsvd11[4];
>  } NvmeIdentify;
>  
>  typedef struct NvmeRwCmd {
> @@ -681,6 +762,23 @@ enum NvmeStatusCodes {
>      NVME_NO_COMPLETE            = 0xffff,
>  };
>  
> +typedef struct NvmeNvmSetAttributes {
> +    uint16_t nvmsetid;
> +    uint16_t endgid;
> +    uint8_t  rsvd7[4];
> +    uint32_t rrt;
> +    uint32_t ows;
> +    uint8_t  tnvmsetcap[16];
> +    uint8_t  unvmsetcap[16];
> +    uint8_t  rsvd127[80];
> +} NvmeNvmSetAttributes;
> +
> +typedef struct NvmeIdNvmSetList {
> +    uint8_t nid;
> +    uint8_t rsvd127[127];
> +    NvmeNvmSetAttributes sets[31];
> +} NvmeIdNvmSetList;
> +
>  typedef struct NvmeFwSlotInfoLog {
>      uint8_t     afi;
>      uint8_t     reserved1[7];
> @@ -734,6 +832,24 @@ enum NvmeSmartWarn {
>      NVME_SMART_FAILED_VOLATILE_MEDIA  = 1 << 4,
>  };
>  
> +typedef struct NvmeEnduranceGroupLog {
> +    uint8_t critical_warning;
> +    uint8_t rsvd2[2];
> +    uint8_t available_spare;
> +    uint8_t available_spare_threshold;
> +    uint8_t percentage_used;
> +    uint8_t rsvd31[26];
> +    uint8_t endurance_estimate[16];
> +    uint8_t data_units_read[16];
> +    uint8_t data_units_written[16];
> +    uint8_t media_units_written[16];
> +    uint8_t host_read_commands[16];
> +    uint8_t host_write_commands[16];
> +    uint8_t media_and_data_integrity_errors[16];
> +    uint8_t number_of_error_information_log_entries[16];
> +    uint8_t rsvd511[352];
> +} NvmeEnduranceGroupLog;
> +
>  enum NvmeLogIdentifier {
>      NVME_LOG_ERROR_INFO     = 0x01,
>      NVME_LOG_SMART_INFO     = 0x02,
> @@ -777,9 +893,14 @@ typedef struct NvmeIdCtrl {
>      uint32_t    rtd3e;
>      uint32_t    oaes;
>      uint32_t    ctratt;
> -    uint8_t     rsvd100[12];
> +    uint16_t    rrls;
> +    uint8_t     rsvd102[9];
> +    uint8_t     cntrltype;
>      uint8_t     fguid[16];
> -    uint8_t     rsvd128[128];
> +    uint16_t    crdt1;
> +    uint16_t    crdt2;
> +    uint16_t    crdt3;
> +    uint8_t     rsvd134[122];
>      uint16_t    oacs;
>      uint8_t     acl;
>      uint8_t     aerl;
> @@ -805,7 +926,16 @@ typedef struct NvmeIdCtrl {
>      uint16_t    mntmt;
>      uint16_t    mxtmt;
>      uint32_t    sanicap;
> -    uint8_t     rsvd332[180];
> +    uint32_t    hmminds;
> +    uint16_t    hmmaxd;
> +    uint16_t    nsetidmax;
> +    uint16_t    endgidmax;
> +    uint8_t     anatt;
> +    uint8_t     anacap;
> +    uint32_t    anagrpmax;
> +    uint32_t    nanagrpid;
> +    uint32_t    pels;
> +    uint8_t     rsvd356[156];
>      uint8_t     sqes;
>      uint8_t     cqes;
>      uint16_t    maxcmd;
> @@ -817,11 +947,12 @@ typedef struct NvmeIdCtrl {
>      uint16_t    awun;
>      uint16_t    awupf;
>      uint8_t     nvscc;
> -    uint8_t     rsvd531;
> +    uint8_t     nwpc;
>      uint16_t    acwu;
>      uint8_t     rsvd534[2];
>      uint32_t    sgls;
> -    uint8_t     rsvd540[228];
> +    uint32_t    mnan;
> +    uint8_t     rsvd544[224];
>      uint8_t     subnqn[256];
>      uint8_t     rsvd1024[1024];
>      NvmePSD     psd[32];
> @@ -976,7 +1107,17 @@ typedef struct NvmeIdNs {
>      uint16_t    nabspf;
>      uint16_t    noiob;
>      uint8_t     nvmcap[16];
> -    uint8_t     rsvd64[40];
> +    uint16_t    npwg;
> +    uint16_t    npwa;
> +    uint16_t    npdg;
> +    uint16_t    npda;
> +    uint16_t    nows;
> +    uint8_t     rsvd74[18];
> +    uint32_t    anagrpid;
> +    uint8_t     rsvd96[3];
> +    uint8_t     nsattr;
> +    uint16_t    nvmsetid;
> +    uint16_t    endgid;
>      uint8_t     nguid[16];
>      uint64_t    eui64;
>      NvmeLBAF    lbaf[16];
> @@ -1048,7 +1189,11 @@ static inline void _nvme_check_size(void)
>      QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) != 64);
>      QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) != 512);
>      QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) != 512);
> +    QEMU_BUILD_BUG_ON(sizeof(NvmeEnduranceGroupLog) != 512);
>      QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) != 4096);
>      QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) != 4096);
> +    QEMU_BUILD_BUG_ON(sizeof(NvmeNvmSetAttributes) != 128);
> +    QEMU_BUILD_BUG_ON(sizeof(NvmeIdNvmSetList) != 4096);
> +    QEMU_BUILD_BUG_ON(sizeof(NvmeBar) != 4096);
>  }
>  #endif
>

Patch
diff mbox series

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 8e147b667c81..07ac409f37c9 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -60,7 +60,7 @@ 
 #define NVME_MAX_IOQPAIRS 0xffff
 #define NVME_REG_SIZE 0x1000
 #define NVME_DB_SIZE  4
-#define NVME_SPEC_VER 0x00010300
+#define NVME_SPEC_VER 0x00010400
 #define NVME_CMB_BIR 2
 #define NVME_PMR_BIR 2
 #define NVME_TEMPERATURE 0x143
@@ -2910,6 +2910,7 @@  static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
     id->ieee[2] = 0xb3;
     id->mdts = n->params.mdts;
     id->ver = cpu_to_le32(NVME_SPEC_VER);
+    id->cntrltype = 0x1;
     id->oacs = cpu_to_le16(0);
 
     /*
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 2a9c5e95bfd2..b27be237cd33 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -7,7 +7,7 @@  typedef struct NvmeBar {
     uint32_t    intms;
     uint32_t    intmc;
     uint32_t    cc;
-    uint32_t    rsvd1;
+    uint8_t     rsvd24[4];
     uint32_t    csts;
     uint32_t    nssrc;
     uint32_t    aqa;
@@ -15,14 +15,20 @@  typedef struct NvmeBar {
     uint64_t    acq;
     uint32_t    cmbloc;
     uint32_t    cmbsz;
-    uint8_t     padding[3520]; /* not used by QEMU */
+    uint32_t    bpinfo;
+    uint32_t    bprsel;
+    uint64_t    bpmbl;
+    uint64_t    cmbmsc;
+    uint32_t    cmbsts;
+    uint8_t     rsvd92[3492];
     uint32_t    pmrcap;
     uint32_t    pmrctl;
     uint32_t    pmrsts;
     uint32_t    pmrebs;
     uint32_t    pmrswtp;
-    uint32_t    pmrmsc;
-} NvmeBar;
+    uint64_t    pmrmsc;
+    uint8_t     rsvd3612[484];
+} QEMU_PACKED NvmeBar;
 
 enum NvmeCapShift {
     CAP_MQES_SHIFT     = 0,
@@ -34,7 +40,8 @@  enum NvmeCapShift {
     CAP_CSS_SHIFT      = 37,
     CAP_MPSMIN_SHIFT   = 48,
     CAP_MPSMAX_SHIFT   = 52,
-    CAP_PMR_SHIFT      = 56,
+    CAP_PMRS_SHIFT     = 56,
+    CAP_CMBS_SHIFT     = 57,
 };
 
 enum NvmeCapMask {
@@ -47,7 +54,8 @@  enum NvmeCapMask {
     CAP_CSS_MASK       = 0xff,
     CAP_MPSMIN_MASK    = 0xf,
     CAP_MPSMAX_MASK    = 0xf,
-    CAP_PMR_MASK       = 0x1,
+    CAP_PMRS_MASK      = 0x1,
+    CAP_CMBS_MASK      = 0x1,
 };
 
 #define NVME_CAP_MQES(cap)  (((cap) >> CAP_MQES_SHIFT)   & CAP_MQES_MASK)
@@ -59,6 +67,8 @@  enum NvmeCapMask {
 #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_PMRS(cap)  (((cap) >> CAP_PMRS_SHIFT)   & CAP_PMRS_MASK)
+#define NVME_CAP_CMBS(cap)  (((cap) >> CAP_CMBS_SHIFT)   & CAP_CMBS_MASK)
 
 #define NVME_CAP_SET_MQES(cap, val)   (cap |= (uint64_t)(val & CAP_MQES_MASK)  \
                                                            << CAP_MQES_SHIFT)
@@ -78,8 +88,10 @@  enum NvmeCapMask {
                                                            << CAP_MPSMIN_SHIFT)
 #define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
                                                             << CAP_MPSMAX_SHIFT)
-#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
-                                                            << CAP_PMR_SHIFT)
+#define NVME_CAP_SET_PMRS(cap, val)   (cap |= (uint64_t)(val & CAP_PMRS_MASK)\
+                                                            << CAP_PMRS_SHIFT)
+#define NVME_CAP_SET_CMBS(cap, val)   (cap |= (uint64_t)(val & CAP_CMBS_MASK)\
+                                                            << CAP_CMBS_SHIFT)
 
 enum NvmeCcShift {
     CC_EN_SHIFT     = 0,
@@ -151,22 +163,58 @@  enum NvmeAqaMask {
 #define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK)
 
 enum NvmeCmblocShift {
-    CMBLOC_BIR_SHIFT  = 0,
-    CMBLOC_OFST_SHIFT = 12,
+    CMBLOC_BIR_SHIFT     = 0,
+    CMBLOC_CQMMS_SHIFT   = 3,
+    CMBLOC_CQPDS_SHIFT   = 4,
+    CMBLOC_CDPMLS_SHIFT  = 5,
+    CMBLOC_CDPCILS_SHIFT = 6,
+    CMBLOC_CDMMMS_SHIFT  = 7,
+    CMBLOC_CQDA_SHIFT    = 8,
+    CMBLOC_OFST_SHIFT    = 12,
 };
 
 enum NvmeCmblocMask {
-    CMBLOC_BIR_MASK  = 0x7,
-    CMBLOC_OFST_MASK = 0xfffff,
+    CMBLOC_BIR_MASK     = 0x7,
+    CMBLOC_CQMMS_MASK   = 0x1,
+    CMBLOC_CQPDS_MASK   = 0x1,
+    CMBLOC_CDPMLS_MASK  = 0x1,
+    CMBLOC_CDPCILS_MASK = 0x1,
+    CMBLOC_CDMMMS_MASK  = 0x1,
+    CMBLOC_CQDA_MASK    = 0x1,
+    CMBLOC_OFST_MASK    = 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_BIR(cmbloc) \
+    ((cmbloc >> CMBLOC_BIR_SHIFT) & CMBLOC_BIR_MASK)
+#define NVME_CMBLOC_CQMMS(cmbloc) \
+    ((cmbloc >> CMBLOC_CQMMS_SHIFT) & CMBLOC_CQMMS_MASK)
+#define NVME_CMBLOC_CQPDS(cmbloc) \
+    ((cmbloc >> CMBLOC_CQPDS_SHIFT) & CMBLOC_CQPDS_MASK)
+#define NVME_CMBLOC_CDPMLS(cmbloc) \
+    ((cmbloc >> CMBLOC_CDPMLS_SHIFT) & CMBLOC_CDPMLS_MASK)
+#define NVME_CMBLOC_CDPCILS(cmbloc) \
+    ((cmbloc >> CMBLOC_CDPCILS_SHIFT) & CMBLOC_CDPCILS_MASK)
+#define NVME_CMBLOC_CDMMS(cmbloc) \
+    ((cmbloc >> CMBLOC_CDMMS_SHIFT) & CMBLOC_CDMMS_MASK)
+#define NVME_CMBLOC_CQDA(cmbloc) \
+    ((cmbloc >> CMBLOC_CQDA_SHIFT) & CMBLOC_CQDA_MASK)
+#define NVME_CMBLOC_OFST(cmbloc) \
+    ((cmbloc >> CMBLOC_OFST_SHIFT) & CMBLOC_OFST_MASK)
 
-#define NVME_CMBLOC_SET_BIR(cmbloc, val)  \
+#define NVME_CMBLOC_SET_BIR(cmbloc, val) \
     (cmbloc |= (uint64_t)(val & CMBLOC_BIR_MASK) << CMBLOC_BIR_SHIFT)
+#define NVME_CMBLOC_SET_CQMMS(cmbloc, val) \
+    (cmbloc |= (uint64_t)(val & CMBLOC_CQMMS_MASK) << CMBLOC_CQMMS_SHIFT)
+#define NVME_CMBLOC_SET_CQPDS(cmbloc, val) \
+    (cmbloc |= (uint64_t)(val & CMBLOC_CQPDS_MASK) << CMBLOC_CQPDS_SHIFT)
+#define NVME_CMBLOC_SET_CDPMLS(cmbloc, val) \
+    (cmbloc |= (uint64_t)(val & CMBLOC_CDPMLS_MASK) << CMBLOC_CDPMLS_SHIFT)
+#define NVME_CMBLOC_SET_CDPCILS(cmbloc, val) \
+    (cmbloc |= (uint64_t)(val & CMBLOC_CDPCILS_MASK) << CMBLOC_CDPCILS_SHIFT)
+#define NVME_CMBLOC_SET_CDMMS(cmbloc, val) \
+    (cmbloc |= (uint64_t)(val & CMBLOC_CDMMS_MASK) << CMBLOC_CDMMS_SHIFT)
+#define NVME_CMBLOC_SET_CQDA(cmbloc, val) \
+    (cmbloc |= (uint64_t)(val & CMBLOC_CQDA_MASK) << CMBLOC_CQDA_SHIFT)
 #define NVME_CMBLOC_SET_OFST(cmbloc, val) \
     (cmbloc |= (uint64_t)(val & CMBLOC_OFST_MASK) << CMBLOC_OFST_SHIFT)
 
@@ -377,6 +425,35 @@  enum NvmePmrmscMask {
 #define NVME_PMRMSC_SET_CBA(pmrmsc, val)   \
     (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
 
+enum NvmeCmbmscShift {
+    CMBMSC_CRE_SHIFT  = 0,
+    CMBMSC_CMSE_SHIFT = 1,
+    CMBMSC_CBA_SHIFT  = 12,
+};
+
+enum NvmeCmbmscMask {
+    CMBMSC_CRE_MASK  = 0x1,
+    CMBMSC_CMSE_MASK = 0x1,
+};
+
+#define CMBMSC_CBA_MASK ((1 << 52) - 1)
+
+#define NVME_CMBMSC_CRE(cmbmsc) \
+    ((cmbmsc >> CMBMSC_CRE_SHIFT)  & CMBMSC_CRE_MASK)
+#define NVME_CMBMSC_CMSE(cmbmsc) \
+    ((cmbmsc >> CMBMSC_CMSE_SHIFT) & CMBMSC_CMSE_MASK)
+#define NVME_CMBMSC_CBA(cmbmsc) \
+    ((cmbmsc >> CMBMSC_CBA_SHIFT)  & CMBMSC_CBA_MASK)
+
+#define NVME_CMBMSC_SET_CRE(cmbmsc, val)  \
+    (cmbmsc |= (uint64_t)(val & CMBMSC_CRE_MASK) << CMBMSC_CRE_SHIFT)
+#define NVME_CMBMSC_SET_CMSE(cmbmsc, val) \
+    (cmbmsc |= (uint64_t)(val & CMBMSC_CMSE_MASK) << CMBMSC_CMSE_SHIFT)
+#define NVME_CMBMSC_SET_CBA(cmbmsc, val)  \
+    (cmbmsc |= (uint64_t)(val & CMBMSC_CBA_MASK) << CMBMSC_CBA_SHIFT)
+
+#define NVME_CMBSTS_CBAI(cmbsts) (cmsts & 0x1)
+
 enum NvmeSglDescriptorType {
     NVME_SGL_DESCR_TYPE_DATA_BLOCK          = 0x0,
     NVME_SGL_DESCR_TYPE_BIT_BUCKET          = 0x1,
@@ -523,8 +600,12 @@  typedef struct NvmeIdentify {
     uint64_t    rsvd2[2];
     uint64_t    prp1;
     uint64_t    prp2;
-    uint32_t    cns;
-    uint32_t    rsvd11[5];
+    uint8_t     cns;
+    uint8_t     rsvd3;
+    uint16_t    cntid;
+    uint16_t    nvmsetid;
+    uint16_t    rsvd4;
+    uint32_t    rsvd11[4];
 } NvmeIdentify;
 
 typedef struct NvmeRwCmd {
@@ -681,6 +762,23 @@  enum NvmeStatusCodes {
     NVME_NO_COMPLETE            = 0xffff,
 };
 
+typedef struct NvmeNvmSetAttributes {
+    uint16_t nvmsetid;
+    uint16_t endgid;
+    uint8_t  rsvd7[4];
+    uint32_t rrt;
+    uint32_t ows;
+    uint8_t  tnvmsetcap[16];
+    uint8_t  unvmsetcap[16];
+    uint8_t  rsvd127[80];
+} NvmeNvmSetAttributes;
+
+typedef struct NvmeIdNvmSetList {
+    uint8_t nid;
+    uint8_t rsvd127[127];
+    NvmeNvmSetAttributes sets[31];
+} NvmeIdNvmSetList;
+
 typedef struct NvmeFwSlotInfoLog {
     uint8_t     afi;
     uint8_t     reserved1[7];
@@ -734,6 +832,24 @@  enum NvmeSmartWarn {
     NVME_SMART_FAILED_VOLATILE_MEDIA  = 1 << 4,
 };
 
+typedef struct NvmeEnduranceGroupLog {
+    uint8_t critical_warning;
+    uint8_t rsvd2[2];
+    uint8_t available_spare;
+    uint8_t available_spare_threshold;
+    uint8_t percentage_used;
+    uint8_t rsvd31[26];
+    uint8_t endurance_estimate[16];
+    uint8_t data_units_read[16];
+    uint8_t data_units_written[16];
+    uint8_t media_units_written[16];
+    uint8_t host_read_commands[16];
+    uint8_t host_write_commands[16];
+    uint8_t media_and_data_integrity_errors[16];
+    uint8_t number_of_error_information_log_entries[16];
+    uint8_t rsvd511[352];
+} NvmeEnduranceGroupLog;
+
 enum NvmeLogIdentifier {
     NVME_LOG_ERROR_INFO     = 0x01,
     NVME_LOG_SMART_INFO     = 0x02,
@@ -777,9 +893,14 @@  typedef struct NvmeIdCtrl {
     uint32_t    rtd3e;
     uint32_t    oaes;
     uint32_t    ctratt;
-    uint8_t     rsvd100[12];
+    uint16_t    rrls;
+    uint8_t     rsvd102[9];
+    uint8_t     cntrltype;
     uint8_t     fguid[16];
-    uint8_t     rsvd128[128];
+    uint16_t    crdt1;
+    uint16_t    crdt2;
+    uint16_t    crdt3;
+    uint8_t     rsvd134[122];
     uint16_t    oacs;
     uint8_t     acl;
     uint8_t     aerl;
@@ -805,7 +926,16 @@  typedef struct NvmeIdCtrl {
     uint16_t    mntmt;
     uint16_t    mxtmt;
     uint32_t    sanicap;
-    uint8_t     rsvd332[180];
+    uint32_t    hmminds;
+    uint16_t    hmmaxd;
+    uint16_t    nsetidmax;
+    uint16_t    endgidmax;
+    uint8_t     anatt;
+    uint8_t     anacap;
+    uint32_t    anagrpmax;
+    uint32_t    nanagrpid;
+    uint32_t    pels;
+    uint8_t     rsvd356[156];
     uint8_t     sqes;
     uint8_t     cqes;
     uint16_t    maxcmd;
@@ -817,11 +947,12 @@  typedef struct NvmeIdCtrl {
     uint16_t    awun;
     uint16_t    awupf;
     uint8_t     nvscc;
-    uint8_t     rsvd531;
+    uint8_t     nwpc;
     uint16_t    acwu;
     uint8_t     rsvd534[2];
     uint32_t    sgls;
-    uint8_t     rsvd540[228];
+    uint32_t    mnan;
+    uint8_t     rsvd544[224];
     uint8_t     subnqn[256];
     uint8_t     rsvd1024[1024];
     NvmePSD     psd[32];
@@ -976,7 +1107,17 @@  typedef struct NvmeIdNs {
     uint16_t    nabspf;
     uint16_t    noiob;
     uint8_t     nvmcap[16];
-    uint8_t     rsvd64[40];
+    uint16_t    npwg;
+    uint16_t    npwa;
+    uint16_t    npdg;
+    uint16_t    npda;
+    uint16_t    nows;
+    uint8_t     rsvd74[18];
+    uint32_t    anagrpid;
+    uint8_t     rsvd96[3];
+    uint8_t     nsattr;
+    uint16_t    nvmsetid;
+    uint16_t    endgid;
     uint8_t     nguid[16];
     uint64_t    eui64;
     NvmeLBAF    lbaf[16];
@@ -1048,7 +1189,11 @@  static inline void _nvme_check_size(void)
     QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) != 64);
     QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) != 512);
     QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) != 512);
+    QEMU_BUILD_BUG_ON(sizeof(NvmeEnduranceGroupLog) != 512);
     QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) != 4096);
     QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) != 4096);
+    QEMU_BUILD_BUG_ON(sizeof(NvmeNvmSetAttributes) != 128);
+    QEMU_BUILD_BUG_ON(sizeof(NvmeIdNvmSetList) != 4096);
+    QEMU_BUILD_BUG_ON(sizeof(NvmeBar) != 4096);
 }
 #endif