1*88eea45cSKlaus Jensen /* 2*88eea45cSKlaus Jensen * QEMU NVM Express 3*88eea45cSKlaus Jensen * 4*88eea45cSKlaus Jensen * Copyright (c) 2012 Intel Corporation 5*88eea45cSKlaus Jensen * Copyright (c) 2021 Minwoo Im 6*88eea45cSKlaus Jensen * Copyright (c) 2021 Samsung Electronics Co., Ltd. 7*88eea45cSKlaus Jensen * 8*88eea45cSKlaus Jensen * Authors: 9*88eea45cSKlaus Jensen * Keith Busch <kbusch@kernel.org> 10*88eea45cSKlaus Jensen * Klaus Jensen <k.jensen@samsung.com> 11*88eea45cSKlaus Jensen * Gollu Appalanaidu <anaidu.gollu@samsung.com> 12*88eea45cSKlaus Jensen * Dmitry Fomichev <dmitry.fomichev@wdc.com> 13*88eea45cSKlaus Jensen * Minwoo Im <minwoo.im.dev@gmail.com> 14*88eea45cSKlaus Jensen * 15*88eea45cSKlaus Jensen * This code is licensed under the GNU GPL v2 or later. 16*88eea45cSKlaus Jensen */ 17*88eea45cSKlaus Jensen 18*88eea45cSKlaus Jensen #ifndef HW_NVME_INTERNAL_H 19*88eea45cSKlaus Jensen #define HW_NVME_INTERNAL_H 20*88eea45cSKlaus Jensen 21*88eea45cSKlaus Jensen #include "qemu/uuid.h" 22*88eea45cSKlaus Jensen #include "hw/pci/pci.h" 23*88eea45cSKlaus Jensen #include "hw/block/block.h" 24*88eea45cSKlaus Jensen 25*88eea45cSKlaus Jensen #include "block/nvme.h" 26*88eea45cSKlaus Jensen 27*88eea45cSKlaus Jensen #define NVME_MAX_CONTROLLERS 32 28*88eea45cSKlaus Jensen #define NVME_MAX_NAMESPACES 256 29*88eea45cSKlaus Jensen 30*88eea45cSKlaus Jensen typedef struct NvmeCtrl NvmeCtrl; 31*88eea45cSKlaus Jensen typedef struct NvmeNamespace NvmeNamespace; 32*88eea45cSKlaus Jensen 33*88eea45cSKlaus Jensen #define TYPE_NVME_SUBSYS "nvme-subsys" 34*88eea45cSKlaus Jensen #define NVME_SUBSYS(obj) \ 35*88eea45cSKlaus Jensen OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS) 36*88eea45cSKlaus Jensen 37*88eea45cSKlaus Jensen typedef struct NvmeSubsystem { 38*88eea45cSKlaus Jensen DeviceState parent_obj; 39*88eea45cSKlaus Jensen uint8_t subnqn[256]; 40*88eea45cSKlaus Jensen 41*88eea45cSKlaus Jensen NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; 42*88eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 43*88eea45cSKlaus Jensen 44*88eea45cSKlaus Jensen struct { 45*88eea45cSKlaus Jensen char *nqn; 46*88eea45cSKlaus Jensen } params; 47*88eea45cSKlaus Jensen } NvmeSubsystem; 48*88eea45cSKlaus Jensen 49*88eea45cSKlaus Jensen int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp); 50*88eea45cSKlaus Jensen 51*88eea45cSKlaus Jensen static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys, 52*88eea45cSKlaus Jensen uint32_t cntlid) 53*88eea45cSKlaus Jensen { 54*88eea45cSKlaus Jensen if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) { 55*88eea45cSKlaus Jensen return NULL; 56*88eea45cSKlaus Jensen } 57*88eea45cSKlaus Jensen 58*88eea45cSKlaus Jensen return subsys->ctrls[cntlid]; 59*88eea45cSKlaus Jensen } 60*88eea45cSKlaus Jensen 61*88eea45cSKlaus Jensen static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys, 62*88eea45cSKlaus Jensen uint32_t nsid) 63*88eea45cSKlaus Jensen { 64*88eea45cSKlaus Jensen if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) { 65*88eea45cSKlaus Jensen return NULL; 66*88eea45cSKlaus Jensen } 67*88eea45cSKlaus Jensen 68*88eea45cSKlaus Jensen return subsys->namespaces[nsid]; 69*88eea45cSKlaus Jensen } 70*88eea45cSKlaus Jensen 71*88eea45cSKlaus Jensen #define TYPE_NVME_NS "nvme-ns" 72*88eea45cSKlaus Jensen #define NVME_NS(obj) \ 73*88eea45cSKlaus Jensen OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) 74*88eea45cSKlaus Jensen 75*88eea45cSKlaus Jensen typedef struct NvmeZone { 76*88eea45cSKlaus Jensen NvmeZoneDescr d; 77*88eea45cSKlaus Jensen uint64_t w_ptr; 78*88eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeZone) entry; 79*88eea45cSKlaus Jensen } NvmeZone; 80*88eea45cSKlaus Jensen 81*88eea45cSKlaus Jensen typedef struct NvmeNamespaceParams { 82*88eea45cSKlaus Jensen bool detached; 83*88eea45cSKlaus Jensen bool shared; 84*88eea45cSKlaus Jensen uint32_t nsid; 85*88eea45cSKlaus Jensen QemuUUID uuid; 86*88eea45cSKlaus Jensen 87*88eea45cSKlaus Jensen uint16_t ms; 88*88eea45cSKlaus Jensen uint8_t mset; 89*88eea45cSKlaus Jensen uint8_t pi; 90*88eea45cSKlaus Jensen uint8_t pil; 91*88eea45cSKlaus Jensen 92*88eea45cSKlaus Jensen uint16_t mssrl; 93*88eea45cSKlaus Jensen uint32_t mcl; 94*88eea45cSKlaus Jensen uint8_t msrc; 95*88eea45cSKlaus Jensen 96*88eea45cSKlaus Jensen bool zoned; 97*88eea45cSKlaus Jensen bool cross_zone_read; 98*88eea45cSKlaus Jensen uint64_t zone_size_bs; 99*88eea45cSKlaus Jensen uint64_t zone_cap_bs; 100*88eea45cSKlaus Jensen uint32_t max_active_zones; 101*88eea45cSKlaus Jensen uint32_t max_open_zones; 102*88eea45cSKlaus Jensen uint32_t zd_extension_size; 103*88eea45cSKlaus Jensen } NvmeNamespaceParams; 104*88eea45cSKlaus Jensen 105*88eea45cSKlaus Jensen typedef struct NvmeNamespace { 106*88eea45cSKlaus Jensen DeviceState parent_obj; 107*88eea45cSKlaus Jensen BlockConf blkconf; 108*88eea45cSKlaus Jensen int32_t bootindex; 109*88eea45cSKlaus Jensen int64_t size; 110*88eea45cSKlaus Jensen int64_t moff; 111*88eea45cSKlaus Jensen NvmeIdNs id_ns; 112*88eea45cSKlaus Jensen NvmeLBAF lbaf; 113*88eea45cSKlaus Jensen size_t lbasz; 114*88eea45cSKlaus Jensen const uint32_t *iocs; 115*88eea45cSKlaus Jensen uint8_t csi; 116*88eea45cSKlaus Jensen uint16_t status; 117*88eea45cSKlaus Jensen int attached; 118*88eea45cSKlaus Jensen 119*88eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeNamespace) entry; 120*88eea45cSKlaus Jensen 121*88eea45cSKlaus Jensen NvmeIdNsZoned *id_ns_zoned; 122*88eea45cSKlaus Jensen NvmeZone *zone_array; 123*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) exp_open_zones; 124*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) imp_open_zones; 125*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) closed_zones; 126*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) full_zones; 127*88eea45cSKlaus Jensen uint32_t num_zones; 128*88eea45cSKlaus Jensen uint64_t zone_size; 129*88eea45cSKlaus Jensen uint64_t zone_capacity; 130*88eea45cSKlaus Jensen uint32_t zone_size_log2; 131*88eea45cSKlaus Jensen uint8_t *zd_extensions; 132*88eea45cSKlaus Jensen int32_t nr_open_zones; 133*88eea45cSKlaus Jensen int32_t nr_active_zones; 134*88eea45cSKlaus Jensen 135*88eea45cSKlaus Jensen NvmeNamespaceParams params; 136*88eea45cSKlaus Jensen 137*88eea45cSKlaus Jensen struct { 138*88eea45cSKlaus Jensen uint32_t err_rec; 139*88eea45cSKlaus Jensen } features; 140*88eea45cSKlaus Jensen } NvmeNamespace; 141*88eea45cSKlaus Jensen 142*88eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns) 143*88eea45cSKlaus Jensen { 144*88eea45cSKlaus Jensen if (ns) { 145*88eea45cSKlaus Jensen return ns->params.nsid; 146*88eea45cSKlaus Jensen } 147*88eea45cSKlaus Jensen 148*88eea45cSKlaus Jensen return 0; 149*88eea45cSKlaus Jensen } 150*88eea45cSKlaus Jensen 151*88eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) 152*88eea45cSKlaus Jensen { 153*88eea45cSKlaus Jensen return lba << ns->lbaf.ds; 154*88eea45cSKlaus Jensen } 155*88eea45cSKlaus Jensen 156*88eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba) 157*88eea45cSKlaus Jensen { 158*88eea45cSKlaus Jensen return ns->lbaf.ms * lba; 159*88eea45cSKlaus Jensen } 160*88eea45cSKlaus Jensen 161*88eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba) 162*88eea45cSKlaus Jensen { 163*88eea45cSKlaus Jensen return ns->moff + nvme_m2b(ns, lba); 164*88eea45cSKlaus Jensen } 165*88eea45cSKlaus Jensen 166*88eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns) 167*88eea45cSKlaus Jensen { 168*88eea45cSKlaus Jensen return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas); 169*88eea45cSKlaus Jensen } 170*88eea45cSKlaus Jensen 171*88eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone) 172*88eea45cSKlaus Jensen { 173*88eea45cSKlaus Jensen return zone->d.zs >> 4; 174*88eea45cSKlaus Jensen } 175*88eea45cSKlaus Jensen 176*88eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state) 177*88eea45cSKlaus Jensen { 178*88eea45cSKlaus Jensen zone->d.zs = state << 4; 179*88eea45cSKlaus Jensen } 180*88eea45cSKlaus Jensen 181*88eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone) 182*88eea45cSKlaus Jensen { 183*88eea45cSKlaus Jensen return zone->d.zslba + ns->zone_size; 184*88eea45cSKlaus Jensen } 185*88eea45cSKlaus Jensen 186*88eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone) 187*88eea45cSKlaus Jensen { 188*88eea45cSKlaus Jensen return zone->d.zslba + zone->d.zcap; 189*88eea45cSKlaus Jensen } 190*88eea45cSKlaus Jensen 191*88eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone) 192*88eea45cSKlaus Jensen { 193*88eea45cSKlaus Jensen uint8_t st = nvme_get_zone_state(zone); 194*88eea45cSKlaus Jensen 195*88eea45cSKlaus Jensen return st != NVME_ZONE_STATE_FULL && 196*88eea45cSKlaus Jensen st != NVME_ZONE_STATE_READ_ONLY && 197*88eea45cSKlaus Jensen st != NVME_ZONE_STATE_OFFLINE; 198*88eea45cSKlaus Jensen } 199*88eea45cSKlaus Jensen 200*88eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns, 201*88eea45cSKlaus Jensen uint32_t zone_idx) 202*88eea45cSKlaus Jensen { 203*88eea45cSKlaus Jensen return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; 204*88eea45cSKlaus Jensen } 205*88eea45cSKlaus Jensen 206*88eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns) 207*88eea45cSKlaus Jensen { 208*88eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 209*88eea45cSKlaus Jensen if (ns->params.max_open_zones) { 210*88eea45cSKlaus Jensen ns->nr_open_zones++; 211*88eea45cSKlaus Jensen assert(ns->nr_open_zones <= ns->params.max_open_zones); 212*88eea45cSKlaus Jensen } 213*88eea45cSKlaus Jensen } 214*88eea45cSKlaus Jensen 215*88eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns) 216*88eea45cSKlaus Jensen { 217*88eea45cSKlaus Jensen if (ns->params.max_open_zones) { 218*88eea45cSKlaus Jensen assert(ns->nr_open_zones > 0); 219*88eea45cSKlaus Jensen ns->nr_open_zones--; 220*88eea45cSKlaus Jensen } 221*88eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 222*88eea45cSKlaus Jensen } 223*88eea45cSKlaus Jensen 224*88eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns) 225*88eea45cSKlaus Jensen { 226*88eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 227*88eea45cSKlaus Jensen if (ns->params.max_active_zones) { 228*88eea45cSKlaus Jensen ns->nr_active_zones++; 229*88eea45cSKlaus Jensen assert(ns->nr_active_zones <= ns->params.max_active_zones); 230*88eea45cSKlaus Jensen } 231*88eea45cSKlaus Jensen } 232*88eea45cSKlaus Jensen 233*88eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns) 234*88eea45cSKlaus Jensen { 235*88eea45cSKlaus Jensen if (ns->params.max_active_zones) { 236*88eea45cSKlaus Jensen assert(ns->nr_active_zones > 0); 237*88eea45cSKlaus Jensen ns->nr_active_zones--; 238*88eea45cSKlaus Jensen assert(ns->nr_active_zones >= ns->nr_open_zones); 239*88eea45cSKlaus Jensen } 240*88eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 241*88eea45cSKlaus Jensen } 242*88eea45cSKlaus Jensen 243*88eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns); 244*88eea45cSKlaus Jensen int nvme_ns_setup(NvmeCtrl *n, NvmeNamespace *ns, Error **errp); 245*88eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns); 246*88eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns); 247*88eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns); 248*88eea45cSKlaus Jensen 249*88eea45cSKlaus Jensen typedef struct NvmeAsyncEvent { 250*88eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeAsyncEvent) entry; 251*88eea45cSKlaus Jensen NvmeAerResult result; 252*88eea45cSKlaus Jensen } NvmeAsyncEvent; 253*88eea45cSKlaus Jensen 254*88eea45cSKlaus Jensen enum { 255*88eea45cSKlaus Jensen NVME_SG_ALLOC = 1 << 0, 256*88eea45cSKlaus Jensen NVME_SG_DMA = 1 << 1, 257*88eea45cSKlaus Jensen }; 258*88eea45cSKlaus Jensen 259*88eea45cSKlaus Jensen typedef struct NvmeSg { 260*88eea45cSKlaus Jensen int flags; 261*88eea45cSKlaus Jensen 262*88eea45cSKlaus Jensen union { 263*88eea45cSKlaus Jensen QEMUSGList qsg; 264*88eea45cSKlaus Jensen QEMUIOVector iov; 265*88eea45cSKlaus Jensen }; 266*88eea45cSKlaus Jensen } NvmeSg; 267*88eea45cSKlaus Jensen 268*88eea45cSKlaus Jensen typedef enum NvmeTxDirection { 269*88eea45cSKlaus Jensen NVME_TX_DIRECTION_TO_DEVICE = 0, 270*88eea45cSKlaus Jensen NVME_TX_DIRECTION_FROM_DEVICE = 1, 271*88eea45cSKlaus Jensen } NvmeTxDirection; 272*88eea45cSKlaus Jensen 273*88eea45cSKlaus Jensen typedef struct NvmeRequest { 274*88eea45cSKlaus Jensen struct NvmeSQueue *sq; 275*88eea45cSKlaus Jensen struct NvmeNamespace *ns; 276*88eea45cSKlaus Jensen BlockAIOCB *aiocb; 277*88eea45cSKlaus Jensen uint16_t status; 278*88eea45cSKlaus Jensen void *opaque; 279*88eea45cSKlaus Jensen NvmeCqe cqe; 280*88eea45cSKlaus Jensen NvmeCmd cmd; 281*88eea45cSKlaus Jensen BlockAcctCookie acct; 282*88eea45cSKlaus Jensen NvmeSg sg; 283*88eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeRequest)entry; 284*88eea45cSKlaus Jensen } NvmeRequest; 285*88eea45cSKlaus Jensen 286*88eea45cSKlaus Jensen typedef struct NvmeBounceContext { 287*88eea45cSKlaus Jensen NvmeRequest *req; 288*88eea45cSKlaus Jensen 289*88eea45cSKlaus Jensen struct { 290*88eea45cSKlaus Jensen QEMUIOVector iov; 291*88eea45cSKlaus Jensen uint8_t *bounce; 292*88eea45cSKlaus Jensen } data, mdata; 293*88eea45cSKlaus Jensen } NvmeBounceContext; 294*88eea45cSKlaus Jensen 295*88eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc) 296*88eea45cSKlaus Jensen { 297*88eea45cSKlaus Jensen switch (opc) { 298*88eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ"; 299*88eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ"; 300*88eea45cSKlaus Jensen case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE"; 301*88eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ"; 302*88eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ"; 303*88eea45cSKlaus Jensen case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY"; 304*88eea45cSKlaus Jensen case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT"; 305*88eea45cSKlaus Jensen case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES"; 306*88eea45cSKlaus Jensen case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES"; 307*88eea45cSKlaus Jensen case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ"; 308*88eea45cSKlaus Jensen case NVME_ADM_CMD_NS_ATTACHMENT: return "NVME_ADM_CMD_NS_ATTACHMENT"; 309*88eea45cSKlaus Jensen case NVME_ADM_CMD_FORMAT_NVM: return "NVME_ADM_CMD_FORMAT_NVM"; 310*88eea45cSKlaus Jensen default: return "NVME_ADM_CMD_UNKNOWN"; 311*88eea45cSKlaus Jensen } 312*88eea45cSKlaus Jensen } 313*88eea45cSKlaus Jensen 314*88eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc) 315*88eea45cSKlaus Jensen { 316*88eea45cSKlaus Jensen switch (opc) { 317*88eea45cSKlaus Jensen case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH"; 318*88eea45cSKlaus Jensen case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE"; 319*88eea45cSKlaus Jensen case NVME_CMD_READ: return "NVME_NVM_CMD_READ"; 320*88eea45cSKlaus Jensen case NVME_CMD_COMPARE: return "NVME_NVM_CMD_COMPARE"; 321*88eea45cSKlaus Jensen case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES"; 322*88eea45cSKlaus Jensen case NVME_CMD_DSM: return "NVME_NVM_CMD_DSM"; 323*88eea45cSKlaus Jensen case NVME_CMD_VERIFY: return "NVME_NVM_CMD_VERIFY"; 324*88eea45cSKlaus Jensen case NVME_CMD_COPY: return "NVME_NVM_CMD_COPY"; 325*88eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND"; 326*88eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV"; 327*88eea45cSKlaus Jensen case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND"; 328*88eea45cSKlaus Jensen default: return "NVME_NVM_CMD_UNKNOWN"; 329*88eea45cSKlaus Jensen } 330*88eea45cSKlaus Jensen } 331*88eea45cSKlaus Jensen 332*88eea45cSKlaus Jensen typedef struct NvmeSQueue { 333*88eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 334*88eea45cSKlaus Jensen uint16_t sqid; 335*88eea45cSKlaus Jensen uint16_t cqid; 336*88eea45cSKlaus Jensen uint32_t head; 337*88eea45cSKlaus Jensen uint32_t tail; 338*88eea45cSKlaus Jensen uint32_t size; 339*88eea45cSKlaus Jensen uint64_t dma_addr; 340*88eea45cSKlaus Jensen QEMUTimer *timer; 341*88eea45cSKlaus Jensen NvmeRequest *io_req; 342*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 343*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) out_req_list; 344*88eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeSQueue) entry; 345*88eea45cSKlaus Jensen } NvmeSQueue; 346*88eea45cSKlaus Jensen 347*88eea45cSKlaus Jensen typedef struct NvmeCQueue { 348*88eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 349*88eea45cSKlaus Jensen uint8_t phase; 350*88eea45cSKlaus Jensen uint16_t cqid; 351*88eea45cSKlaus Jensen uint16_t irq_enabled; 352*88eea45cSKlaus Jensen uint32_t head; 353*88eea45cSKlaus Jensen uint32_t tail; 354*88eea45cSKlaus Jensen uint32_t vector; 355*88eea45cSKlaus Jensen uint32_t size; 356*88eea45cSKlaus Jensen uint64_t dma_addr; 357*88eea45cSKlaus Jensen QEMUTimer *timer; 358*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeSQueue) sq_list; 359*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 360*88eea45cSKlaus Jensen } NvmeCQueue; 361*88eea45cSKlaus Jensen 362*88eea45cSKlaus Jensen #define TYPE_NVME_BUS "nvme-bus" 363*88eea45cSKlaus Jensen #define NVME_BUS(obj) OBJECT_CHECK(NvmeBus, (obj), TYPE_NVME_BUS) 364*88eea45cSKlaus Jensen 365*88eea45cSKlaus Jensen typedef struct NvmeBus { 366*88eea45cSKlaus Jensen BusState parent_bus; 367*88eea45cSKlaus Jensen } NvmeBus; 368*88eea45cSKlaus Jensen 369*88eea45cSKlaus Jensen #define TYPE_NVME "nvme" 370*88eea45cSKlaus Jensen #define NVME(obj) \ 371*88eea45cSKlaus Jensen OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) 372*88eea45cSKlaus Jensen 373*88eea45cSKlaus Jensen typedef struct NvmeParams { 374*88eea45cSKlaus Jensen char *serial; 375*88eea45cSKlaus Jensen uint32_t num_queues; /* deprecated since 5.1 */ 376*88eea45cSKlaus Jensen uint32_t max_ioqpairs; 377*88eea45cSKlaus Jensen uint16_t msix_qsize; 378*88eea45cSKlaus Jensen uint32_t cmb_size_mb; 379*88eea45cSKlaus Jensen uint8_t aerl; 380*88eea45cSKlaus Jensen uint32_t aer_max_queued; 381*88eea45cSKlaus Jensen uint8_t mdts; 382*88eea45cSKlaus Jensen uint8_t vsl; 383*88eea45cSKlaus Jensen bool use_intel_id; 384*88eea45cSKlaus Jensen uint8_t zasl; 385*88eea45cSKlaus Jensen bool legacy_cmb; 386*88eea45cSKlaus Jensen } NvmeParams; 387*88eea45cSKlaus Jensen 388*88eea45cSKlaus Jensen typedef struct NvmeCtrl { 389*88eea45cSKlaus Jensen PCIDevice parent_obj; 390*88eea45cSKlaus Jensen MemoryRegion bar0; 391*88eea45cSKlaus Jensen MemoryRegion iomem; 392*88eea45cSKlaus Jensen NvmeBar bar; 393*88eea45cSKlaus Jensen NvmeParams params; 394*88eea45cSKlaus Jensen NvmeBus bus; 395*88eea45cSKlaus Jensen 396*88eea45cSKlaus Jensen uint16_t cntlid; 397*88eea45cSKlaus Jensen bool qs_created; 398*88eea45cSKlaus Jensen uint32_t page_size; 399*88eea45cSKlaus Jensen uint16_t page_bits; 400*88eea45cSKlaus Jensen uint16_t max_prp_ents; 401*88eea45cSKlaus Jensen uint16_t cqe_size; 402*88eea45cSKlaus Jensen uint16_t sqe_size; 403*88eea45cSKlaus Jensen uint32_t reg_size; 404*88eea45cSKlaus Jensen uint32_t max_q_ents; 405*88eea45cSKlaus Jensen uint8_t outstanding_aers; 406*88eea45cSKlaus Jensen uint32_t irq_status; 407*88eea45cSKlaus Jensen uint64_t host_timestamp; /* Timestamp sent by the host */ 408*88eea45cSKlaus Jensen uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ 409*88eea45cSKlaus Jensen uint64_t starttime_ms; 410*88eea45cSKlaus Jensen uint16_t temperature; 411*88eea45cSKlaus Jensen uint8_t smart_critical_warning; 412*88eea45cSKlaus Jensen 413*88eea45cSKlaus Jensen struct { 414*88eea45cSKlaus Jensen MemoryRegion mem; 415*88eea45cSKlaus Jensen uint8_t *buf; 416*88eea45cSKlaus Jensen bool cmse; 417*88eea45cSKlaus Jensen hwaddr cba; 418*88eea45cSKlaus Jensen } cmb; 419*88eea45cSKlaus Jensen 420*88eea45cSKlaus Jensen struct { 421*88eea45cSKlaus Jensen HostMemoryBackend *dev; 422*88eea45cSKlaus Jensen bool cmse; 423*88eea45cSKlaus Jensen hwaddr cba; 424*88eea45cSKlaus Jensen } pmr; 425*88eea45cSKlaus Jensen 426*88eea45cSKlaus Jensen uint8_t aer_mask; 427*88eea45cSKlaus Jensen NvmeRequest **aer_reqs; 428*88eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue; 429*88eea45cSKlaus Jensen int aer_queued; 430*88eea45cSKlaus Jensen 431*88eea45cSKlaus Jensen uint32_t dmrsl; 432*88eea45cSKlaus Jensen 433*88eea45cSKlaus Jensen /* Namespace ID is started with 1 so bitmap should be 1-based */ 434*88eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1) 435*88eea45cSKlaus Jensen DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE); 436*88eea45cSKlaus Jensen 437*88eea45cSKlaus Jensen NvmeSubsystem *subsys; 438*88eea45cSKlaus Jensen 439*88eea45cSKlaus Jensen NvmeNamespace namespace; 440*88eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 441*88eea45cSKlaus Jensen NvmeSQueue **sq; 442*88eea45cSKlaus Jensen NvmeCQueue **cq; 443*88eea45cSKlaus Jensen NvmeSQueue admin_sq; 444*88eea45cSKlaus Jensen NvmeCQueue admin_cq; 445*88eea45cSKlaus Jensen NvmeIdCtrl id_ctrl; 446*88eea45cSKlaus Jensen 447*88eea45cSKlaus Jensen struct { 448*88eea45cSKlaus Jensen struct { 449*88eea45cSKlaus Jensen uint16_t temp_thresh_hi; 450*88eea45cSKlaus Jensen uint16_t temp_thresh_low; 451*88eea45cSKlaus Jensen }; 452*88eea45cSKlaus Jensen uint32_t async_config; 453*88eea45cSKlaus Jensen } features; 454*88eea45cSKlaus Jensen } NvmeCtrl; 455*88eea45cSKlaus Jensen 456*88eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) 457*88eea45cSKlaus Jensen { 458*88eea45cSKlaus Jensen if (!nsid || nsid > NVME_MAX_NAMESPACES) { 459*88eea45cSKlaus Jensen return NULL; 460*88eea45cSKlaus Jensen } 461*88eea45cSKlaus Jensen 462*88eea45cSKlaus Jensen return n->namespaces[nsid]; 463*88eea45cSKlaus Jensen } 464*88eea45cSKlaus Jensen 465*88eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req) 466*88eea45cSKlaus Jensen { 467*88eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 468*88eea45cSKlaus Jensen NvmeCtrl *n = sq->ctrl; 469*88eea45cSKlaus Jensen 470*88eea45cSKlaus Jensen return n->cq[sq->cqid]; 471*88eea45cSKlaus Jensen } 472*88eea45cSKlaus Jensen 473*88eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req) 474*88eea45cSKlaus Jensen { 475*88eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 476*88eea45cSKlaus Jensen return sq->ctrl; 477*88eea45cSKlaus Jensen } 478*88eea45cSKlaus Jensen 479*88eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req) 480*88eea45cSKlaus Jensen { 481*88eea45cSKlaus Jensen if (!req) { 482*88eea45cSKlaus Jensen return 0xffff; 483*88eea45cSKlaus Jensen } 484*88eea45cSKlaus Jensen 485*88eea45cSKlaus Jensen return le16_to_cpu(req->cqe.cid); 486*88eea45cSKlaus Jensen } 487*88eea45cSKlaus Jensen 488*88eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); 489*88eea45cSKlaus Jensen uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, 490*88eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 491*88eea45cSKlaus Jensen uint16_t nvme_bounce_mdata(NvmeCtrl *n, uint8_t *ptr, uint32_t len, 492*88eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 493*88eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret); 494*88eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, 495*88eea45cSKlaus Jensen NvmeCmd *cmd); 496*88eea45cSKlaus Jensen 497*88eea45cSKlaus Jensen /* from Linux kernel (crypto/crct10dif_common.c) */ 498*88eea45cSKlaus Jensen static const uint16_t t10_dif_crc_table[256] = { 499*88eea45cSKlaus Jensen 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, 500*88eea45cSKlaus Jensen 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, 501*88eea45cSKlaus Jensen 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, 502*88eea45cSKlaus Jensen 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, 503*88eea45cSKlaus Jensen 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, 504*88eea45cSKlaus Jensen 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, 505*88eea45cSKlaus Jensen 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, 506*88eea45cSKlaus Jensen 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, 507*88eea45cSKlaus Jensen 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, 508*88eea45cSKlaus Jensen 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, 509*88eea45cSKlaus Jensen 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, 510*88eea45cSKlaus Jensen 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, 511*88eea45cSKlaus Jensen 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, 512*88eea45cSKlaus Jensen 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, 513*88eea45cSKlaus Jensen 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, 514*88eea45cSKlaus Jensen 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, 515*88eea45cSKlaus Jensen 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, 516*88eea45cSKlaus Jensen 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, 517*88eea45cSKlaus Jensen 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, 518*88eea45cSKlaus Jensen 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, 519*88eea45cSKlaus Jensen 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, 520*88eea45cSKlaus Jensen 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, 521*88eea45cSKlaus Jensen 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, 522*88eea45cSKlaus Jensen 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, 523*88eea45cSKlaus Jensen 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, 524*88eea45cSKlaus Jensen 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, 525*88eea45cSKlaus Jensen 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, 526*88eea45cSKlaus Jensen 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, 527*88eea45cSKlaus Jensen 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, 528*88eea45cSKlaus Jensen 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, 529*88eea45cSKlaus Jensen 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, 530*88eea45cSKlaus Jensen 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 531*88eea45cSKlaus Jensen }; 532*88eea45cSKlaus Jensen 533*88eea45cSKlaus Jensen uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint16_t ctrl, uint64_t slba, 534*88eea45cSKlaus Jensen uint32_t reftag); 535*88eea45cSKlaus Jensen uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, 536*88eea45cSKlaus Jensen uint64_t slba); 537*88eea45cSKlaus Jensen void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, 538*88eea45cSKlaus Jensen uint8_t *mbuf, size_t mlen, uint16_t apptag, 539*88eea45cSKlaus Jensen uint32_t reftag); 540*88eea45cSKlaus Jensen uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, 541*88eea45cSKlaus Jensen uint8_t *mbuf, size_t mlen, uint16_t ctrl, 542*88eea45cSKlaus Jensen uint64_t slba, uint16_t apptag, 543*88eea45cSKlaus Jensen uint16_t appmask, uint32_t reftag); 544*88eea45cSKlaus Jensen uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req); 545*88eea45cSKlaus Jensen 546*88eea45cSKlaus Jensen 547*88eea45cSKlaus Jensen #endif /* HW_NVME_INTERNAL_H */ 548