188eea45cSKlaus Jensen /* 288eea45cSKlaus Jensen * QEMU NVM Express 388eea45cSKlaus Jensen * 488eea45cSKlaus Jensen * Copyright (c) 2012 Intel Corporation 588eea45cSKlaus Jensen * Copyright (c) 2021 Minwoo Im 688eea45cSKlaus Jensen * Copyright (c) 2021 Samsung Electronics Co., Ltd. 788eea45cSKlaus Jensen * 888eea45cSKlaus Jensen * Authors: 988eea45cSKlaus Jensen * Keith Busch <kbusch@kernel.org> 1088eea45cSKlaus Jensen * Klaus Jensen <k.jensen@samsung.com> 1188eea45cSKlaus Jensen * Gollu Appalanaidu <anaidu.gollu@samsung.com> 1288eea45cSKlaus Jensen * Dmitry Fomichev <dmitry.fomichev@wdc.com> 1388eea45cSKlaus Jensen * Minwoo Im <minwoo.im.dev@gmail.com> 1488eea45cSKlaus Jensen * 1588eea45cSKlaus Jensen * This code is licensed under the GNU GPL v2 or later. 1688eea45cSKlaus Jensen */ 1788eea45cSKlaus Jensen 1852581c71SMarkus Armbruster #ifndef HW_NVME_NVME_H 1952581c71SMarkus Armbruster #define HW_NVME_NVME_H 2088eea45cSKlaus Jensen 2188eea45cSKlaus Jensen #include "qemu/uuid.h" 2288eea45cSKlaus Jensen #include "hw/pci/pci.h" 2388eea45cSKlaus Jensen #include "hw/block/block.h" 2488eea45cSKlaus Jensen 2588eea45cSKlaus Jensen #include "block/nvme.h" 2688eea45cSKlaus Jensen 27*44c2c094SLukasz Maniak #define NVME_MAX_CONTROLLERS 256 2888eea45cSKlaus Jensen #define NVME_MAX_NAMESPACES 256 293276dde4SHeinrich Schuchardt #define NVME_EUI64_DEFAULT ((uint64_t)0x5254000000000000) 3088eea45cSKlaus Jensen 3138f4ac65SKlaus Jensen QEMU_BUILD_BUG_ON(NVME_MAX_NAMESPACES > NVME_NSID_BROADCAST - 1); 3238f4ac65SKlaus Jensen 3388eea45cSKlaus Jensen typedef struct NvmeCtrl NvmeCtrl; 3488eea45cSKlaus Jensen typedef struct NvmeNamespace NvmeNamespace; 3588eea45cSKlaus Jensen 365ffbaeedSKlaus Jensen #define TYPE_NVME_BUS "nvme-bus" 375ffbaeedSKlaus Jensen OBJECT_DECLARE_SIMPLE_TYPE(NvmeBus, NVME_BUS) 385ffbaeedSKlaus Jensen 395ffbaeedSKlaus Jensen typedef struct NvmeBus { 405ffbaeedSKlaus Jensen BusState parent_bus; 415ffbaeedSKlaus Jensen } NvmeBus; 425ffbaeedSKlaus Jensen 4388eea45cSKlaus Jensen #define TYPE_NVME_SUBSYS "nvme-subsys" 4488eea45cSKlaus Jensen #define NVME_SUBSYS(obj) \ 4588eea45cSKlaus Jensen OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS) 4688eea45cSKlaus Jensen 4788eea45cSKlaus Jensen typedef struct NvmeSubsystem { 4888eea45cSKlaus Jensen DeviceState parent_obj; 495ffbaeedSKlaus Jensen NvmeBus bus; 5088eea45cSKlaus Jensen uint8_t subnqn[256]; 51a859eb9fSKlaus Jensen char *serial; 5288eea45cSKlaus Jensen 5388eea45cSKlaus Jensen NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; 5488eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 5588eea45cSKlaus Jensen 5688eea45cSKlaus Jensen struct { 5788eea45cSKlaus Jensen char *nqn; 5888eea45cSKlaus Jensen } params; 5988eea45cSKlaus Jensen } NvmeSubsystem; 6088eea45cSKlaus Jensen 6188eea45cSKlaus Jensen int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp); 62b0fde9e8SKlaus Jensen void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n); 6388eea45cSKlaus Jensen 6488eea45cSKlaus Jensen static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys, 6588eea45cSKlaus Jensen uint32_t cntlid) 6688eea45cSKlaus Jensen { 6788eea45cSKlaus Jensen if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) { 6888eea45cSKlaus Jensen return NULL; 6988eea45cSKlaus Jensen } 7088eea45cSKlaus Jensen 7188eea45cSKlaus Jensen return subsys->ctrls[cntlid]; 7288eea45cSKlaus Jensen } 7388eea45cSKlaus Jensen 7488eea45cSKlaus Jensen static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys, 7588eea45cSKlaus Jensen uint32_t nsid) 7688eea45cSKlaus Jensen { 7788eea45cSKlaus Jensen if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) { 7888eea45cSKlaus Jensen return NULL; 7988eea45cSKlaus Jensen } 8088eea45cSKlaus Jensen 8188eea45cSKlaus Jensen return subsys->namespaces[nsid]; 8288eea45cSKlaus Jensen } 8388eea45cSKlaus Jensen 8488eea45cSKlaus Jensen #define TYPE_NVME_NS "nvme-ns" 8588eea45cSKlaus Jensen #define NVME_NS(obj) \ 8688eea45cSKlaus Jensen OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) 8788eea45cSKlaus Jensen 8888eea45cSKlaus Jensen typedef struct NvmeZone { 8988eea45cSKlaus Jensen NvmeZoneDescr d; 9088eea45cSKlaus Jensen uint64_t w_ptr; 9188eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeZone) entry; 9288eea45cSKlaus Jensen } NvmeZone; 9388eea45cSKlaus Jensen 9488eea45cSKlaus Jensen typedef struct NvmeNamespaceParams { 9588eea45cSKlaus Jensen bool detached; 9688eea45cSKlaus Jensen bool shared; 9788eea45cSKlaus Jensen uint32_t nsid; 9888eea45cSKlaus Jensen QemuUUID uuid; 996870cfb8SHeinrich Schuchardt uint64_t eui64; 1003276dde4SHeinrich Schuchardt bool eui64_default; 10188eea45cSKlaus Jensen 10288eea45cSKlaus Jensen uint16_t ms; 10388eea45cSKlaus Jensen uint8_t mset; 10488eea45cSKlaus Jensen uint8_t pi; 10588eea45cSKlaus Jensen uint8_t pil; 10644219b60SNaveen Nagar uint8_t pif; 10788eea45cSKlaus Jensen 10888eea45cSKlaus Jensen uint16_t mssrl; 10988eea45cSKlaus Jensen uint32_t mcl; 11088eea45cSKlaus Jensen uint8_t msrc; 11188eea45cSKlaus Jensen 11288eea45cSKlaus Jensen bool zoned; 11388eea45cSKlaus Jensen bool cross_zone_read; 11488eea45cSKlaus Jensen uint64_t zone_size_bs; 11588eea45cSKlaus Jensen uint64_t zone_cap_bs; 11688eea45cSKlaus Jensen uint32_t max_active_zones; 11788eea45cSKlaus Jensen uint32_t max_open_zones; 11888eea45cSKlaus Jensen uint32_t zd_extension_size; 119e321b4cdSKlaus Jensen 120e321b4cdSKlaus Jensen uint32_t numzrwa; 121e321b4cdSKlaus Jensen uint64_t zrwas; 122e321b4cdSKlaus Jensen uint64_t zrwafg; 12388eea45cSKlaus Jensen } NvmeNamespaceParams; 12488eea45cSKlaus Jensen 12588eea45cSKlaus Jensen typedef struct NvmeNamespace { 12688eea45cSKlaus Jensen DeviceState parent_obj; 12788eea45cSKlaus Jensen BlockConf blkconf; 12888eea45cSKlaus Jensen int32_t bootindex; 12988eea45cSKlaus Jensen int64_t size; 13088eea45cSKlaus Jensen int64_t moff; 13188eea45cSKlaus Jensen NvmeIdNs id_ns; 13244219b60SNaveen Nagar NvmeIdNsNvm id_ns_nvm; 13388eea45cSKlaus Jensen NvmeLBAF lbaf; 134763c05dfSNaveen Nagar unsigned int nlbaf; 13588eea45cSKlaus Jensen size_t lbasz; 13688eea45cSKlaus Jensen const uint32_t *iocs; 13788eea45cSKlaus Jensen uint8_t csi; 13888eea45cSKlaus Jensen uint16_t status; 13988eea45cSKlaus Jensen int attached; 14044219b60SNaveen Nagar uint8_t pif; 14188eea45cSKlaus Jensen 142e321b4cdSKlaus Jensen struct { 143e321b4cdSKlaus Jensen uint16_t zrwas; 144e321b4cdSKlaus Jensen uint16_t zrwafg; 145e321b4cdSKlaus Jensen uint32_t numzrwa; 146e321b4cdSKlaus Jensen } zns; 147e321b4cdSKlaus Jensen 14888eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeNamespace) entry; 14988eea45cSKlaus Jensen 15088eea45cSKlaus Jensen NvmeIdNsZoned *id_ns_zoned; 15188eea45cSKlaus Jensen NvmeZone *zone_array; 15288eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) exp_open_zones; 15388eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) imp_open_zones; 15488eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) closed_zones; 15588eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) full_zones; 15688eea45cSKlaus Jensen uint32_t num_zones; 15788eea45cSKlaus Jensen uint64_t zone_size; 15888eea45cSKlaus Jensen uint64_t zone_capacity; 15988eea45cSKlaus Jensen uint32_t zone_size_log2; 16088eea45cSKlaus Jensen uint8_t *zd_extensions; 16188eea45cSKlaus Jensen int32_t nr_open_zones; 16288eea45cSKlaus Jensen int32_t nr_active_zones; 16388eea45cSKlaus Jensen 16488eea45cSKlaus Jensen NvmeNamespaceParams params; 16588eea45cSKlaus Jensen 16688eea45cSKlaus Jensen struct { 16788eea45cSKlaus Jensen uint32_t err_rec; 16888eea45cSKlaus Jensen } features; 16988eea45cSKlaus Jensen } NvmeNamespace; 17088eea45cSKlaus Jensen 17188eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns) 17288eea45cSKlaus Jensen { 17388eea45cSKlaus Jensen if (ns) { 17488eea45cSKlaus Jensen return ns->params.nsid; 17588eea45cSKlaus Jensen } 17688eea45cSKlaus Jensen 17788eea45cSKlaus Jensen return 0; 17888eea45cSKlaus Jensen } 17988eea45cSKlaus Jensen 18088eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) 18188eea45cSKlaus Jensen { 18288eea45cSKlaus Jensen return lba << ns->lbaf.ds; 18388eea45cSKlaus Jensen } 18488eea45cSKlaus Jensen 18588eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba) 18688eea45cSKlaus Jensen { 18788eea45cSKlaus Jensen return ns->lbaf.ms * lba; 18888eea45cSKlaus Jensen } 18988eea45cSKlaus Jensen 19088eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba) 19188eea45cSKlaus Jensen { 19288eea45cSKlaus Jensen return ns->moff + nvme_m2b(ns, lba); 19388eea45cSKlaus Jensen } 19488eea45cSKlaus Jensen 19588eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns) 19688eea45cSKlaus Jensen { 19788eea45cSKlaus Jensen return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas); 19888eea45cSKlaus Jensen } 19988eea45cSKlaus Jensen 20088eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone) 20188eea45cSKlaus Jensen { 20288eea45cSKlaus Jensen return zone->d.zs >> 4; 20388eea45cSKlaus Jensen } 20488eea45cSKlaus Jensen 20588eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state) 20688eea45cSKlaus Jensen { 20788eea45cSKlaus Jensen zone->d.zs = state << 4; 20888eea45cSKlaus Jensen } 20988eea45cSKlaus Jensen 21088eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone) 21188eea45cSKlaus Jensen { 21288eea45cSKlaus Jensen return zone->d.zslba + ns->zone_size; 21388eea45cSKlaus Jensen } 21488eea45cSKlaus Jensen 21588eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone) 21688eea45cSKlaus Jensen { 21788eea45cSKlaus Jensen return zone->d.zslba + zone->d.zcap; 21888eea45cSKlaus Jensen } 21988eea45cSKlaus Jensen 22088eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone) 22188eea45cSKlaus Jensen { 22288eea45cSKlaus Jensen uint8_t st = nvme_get_zone_state(zone); 22388eea45cSKlaus Jensen 22488eea45cSKlaus Jensen return st != NVME_ZONE_STATE_FULL && 22588eea45cSKlaus Jensen st != NVME_ZONE_STATE_READ_ONLY && 22688eea45cSKlaus Jensen st != NVME_ZONE_STATE_OFFLINE; 22788eea45cSKlaus Jensen } 22888eea45cSKlaus Jensen 22988eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns, 23088eea45cSKlaus Jensen uint32_t zone_idx) 23188eea45cSKlaus Jensen { 23288eea45cSKlaus Jensen return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; 23388eea45cSKlaus Jensen } 23488eea45cSKlaus Jensen 23588eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns) 23688eea45cSKlaus Jensen { 23788eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 23888eea45cSKlaus Jensen if (ns->params.max_open_zones) { 23988eea45cSKlaus Jensen ns->nr_open_zones++; 24088eea45cSKlaus Jensen assert(ns->nr_open_zones <= ns->params.max_open_zones); 24188eea45cSKlaus Jensen } 24288eea45cSKlaus Jensen } 24388eea45cSKlaus Jensen 24488eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns) 24588eea45cSKlaus Jensen { 24688eea45cSKlaus Jensen if (ns->params.max_open_zones) { 24788eea45cSKlaus Jensen assert(ns->nr_open_zones > 0); 24888eea45cSKlaus Jensen ns->nr_open_zones--; 24988eea45cSKlaus Jensen } 25088eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 25188eea45cSKlaus Jensen } 25288eea45cSKlaus Jensen 25388eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns) 25488eea45cSKlaus Jensen { 25588eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 25688eea45cSKlaus Jensen if (ns->params.max_active_zones) { 25788eea45cSKlaus Jensen ns->nr_active_zones++; 25888eea45cSKlaus Jensen assert(ns->nr_active_zones <= ns->params.max_active_zones); 25988eea45cSKlaus Jensen } 26088eea45cSKlaus Jensen } 26188eea45cSKlaus Jensen 26288eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns) 26388eea45cSKlaus Jensen { 26488eea45cSKlaus Jensen if (ns->params.max_active_zones) { 26588eea45cSKlaus Jensen assert(ns->nr_active_zones > 0); 26688eea45cSKlaus Jensen ns->nr_active_zones--; 26788eea45cSKlaus Jensen assert(ns->nr_active_zones >= ns->nr_open_zones); 26888eea45cSKlaus Jensen } 26988eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 27088eea45cSKlaus Jensen } 27188eea45cSKlaus Jensen 27288eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns); 2735e4f6bccSKlaus Jensen int nvme_ns_setup(NvmeNamespace *ns, Error **errp); 27488eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns); 27588eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns); 27688eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns); 27788eea45cSKlaus Jensen 27888eea45cSKlaus Jensen typedef struct NvmeAsyncEvent { 27988eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeAsyncEvent) entry; 28088eea45cSKlaus Jensen NvmeAerResult result; 28188eea45cSKlaus Jensen } NvmeAsyncEvent; 28288eea45cSKlaus Jensen 28388eea45cSKlaus Jensen enum { 28488eea45cSKlaus Jensen NVME_SG_ALLOC = 1 << 0, 28588eea45cSKlaus Jensen NVME_SG_DMA = 1 << 1, 28688eea45cSKlaus Jensen }; 28788eea45cSKlaus Jensen 28888eea45cSKlaus Jensen typedef struct NvmeSg { 28988eea45cSKlaus Jensen int flags; 29088eea45cSKlaus Jensen 29188eea45cSKlaus Jensen union { 29288eea45cSKlaus Jensen QEMUSGList qsg; 29388eea45cSKlaus Jensen QEMUIOVector iov; 29488eea45cSKlaus Jensen }; 29588eea45cSKlaus Jensen } NvmeSg; 29688eea45cSKlaus Jensen 29788eea45cSKlaus Jensen typedef enum NvmeTxDirection { 29888eea45cSKlaus Jensen NVME_TX_DIRECTION_TO_DEVICE = 0, 29988eea45cSKlaus Jensen NVME_TX_DIRECTION_FROM_DEVICE = 1, 30088eea45cSKlaus Jensen } NvmeTxDirection; 30188eea45cSKlaus Jensen 30288eea45cSKlaus Jensen typedef struct NvmeRequest { 30388eea45cSKlaus Jensen struct NvmeSQueue *sq; 30488eea45cSKlaus Jensen struct NvmeNamespace *ns; 30588eea45cSKlaus Jensen BlockAIOCB *aiocb; 30688eea45cSKlaus Jensen uint16_t status; 30788eea45cSKlaus Jensen void *opaque; 30888eea45cSKlaus Jensen NvmeCqe cqe; 30988eea45cSKlaus Jensen NvmeCmd cmd; 31088eea45cSKlaus Jensen BlockAcctCookie acct; 31188eea45cSKlaus Jensen NvmeSg sg; 31288eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeRequest)entry; 31388eea45cSKlaus Jensen } NvmeRequest; 31488eea45cSKlaus Jensen 31588eea45cSKlaus Jensen typedef struct NvmeBounceContext { 31688eea45cSKlaus Jensen NvmeRequest *req; 31788eea45cSKlaus Jensen 31888eea45cSKlaus Jensen struct { 31988eea45cSKlaus Jensen QEMUIOVector iov; 32088eea45cSKlaus Jensen uint8_t *bounce; 32188eea45cSKlaus Jensen } data, mdata; 32288eea45cSKlaus Jensen } NvmeBounceContext; 32388eea45cSKlaus Jensen 32488eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc) 32588eea45cSKlaus Jensen { 32688eea45cSKlaus Jensen switch (opc) { 32788eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ"; 32888eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ"; 32988eea45cSKlaus Jensen case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE"; 33088eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ"; 33188eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ"; 33288eea45cSKlaus Jensen case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY"; 33388eea45cSKlaus Jensen case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT"; 33488eea45cSKlaus Jensen case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES"; 33588eea45cSKlaus Jensen case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES"; 33688eea45cSKlaus Jensen case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ"; 33788eea45cSKlaus Jensen case NVME_ADM_CMD_NS_ATTACHMENT: return "NVME_ADM_CMD_NS_ATTACHMENT"; 33888eea45cSKlaus Jensen case NVME_ADM_CMD_FORMAT_NVM: return "NVME_ADM_CMD_FORMAT_NVM"; 33988eea45cSKlaus Jensen default: return "NVME_ADM_CMD_UNKNOWN"; 34088eea45cSKlaus Jensen } 34188eea45cSKlaus Jensen } 34288eea45cSKlaus Jensen 34388eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc) 34488eea45cSKlaus Jensen { 34588eea45cSKlaus Jensen switch (opc) { 34688eea45cSKlaus Jensen case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH"; 34788eea45cSKlaus Jensen case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE"; 34888eea45cSKlaus Jensen case NVME_CMD_READ: return "NVME_NVM_CMD_READ"; 34988eea45cSKlaus Jensen case NVME_CMD_COMPARE: return "NVME_NVM_CMD_COMPARE"; 35088eea45cSKlaus Jensen case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES"; 35188eea45cSKlaus Jensen case NVME_CMD_DSM: return "NVME_NVM_CMD_DSM"; 35288eea45cSKlaus Jensen case NVME_CMD_VERIFY: return "NVME_NVM_CMD_VERIFY"; 35388eea45cSKlaus Jensen case NVME_CMD_COPY: return "NVME_NVM_CMD_COPY"; 35488eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND"; 35588eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV"; 35688eea45cSKlaus Jensen case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND"; 35788eea45cSKlaus Jensen default: return "NVME_NVM_CMD_UNKNOWN"; 35888eea45cSKlaus Jensen } 35988eea45cSKlaus Jensen } 36088eea45cSKlaus Jensen 36188eea45cSKlaus Jensen typedef struct NvmeSQueue { 36288eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 36388eea45cSKlaus Jensen uint16_t sqid; 36488eea45cSKlaus Jensen uint16_t cqid; 36588eea45cSKlaus Jensen uint32_t head; 36688eea45cSKlaus Jensen uint32_t tail; 36788eea45cSKlaus Jensen uint32_t size; 36888eea45cSKlaus Jensen uint64_t dma_addr; 36988eea45cSKlaus Jensen QEMUTimer *timer; 37088eea45cSKlaus Jensen NvmeRequest *io_req; 37188eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 37288eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) out_req_list; 37388eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeSQueue) entry; 37488eea45cSKlaus Jensen } NvmeSQueue; 37588eea45cSKlaus Jensen 37688eea45cSKlaus Jensen typedef struct NvmeCQueue { 37788eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 37888eea45cSKlaus Jensen uint8_t phase; 37988eea45cSKlaus Jensen uint16_t cqid; 38088eea45cSKlaus Jensen uint16_t irq_enabled; 38188eea45cSKlaus Jensen uint32_t head; 38288eea45cSKlaus Jensen uint32_t tail; 38388eea45cSKlaus Jensen uint32_t vector; 38488eea45cSKlaus Jensen uint32_t size; 38588eea45cSKlaus Jensen uint64_t dma_addr; 38688eea45cSKlaus Jensen QEMUTimer *timer; 38788eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeSQueue) sq_list; 38888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 38988eea45cSKlaus Jensen } NvmeCQueue; 39088eea45cSKlaus Jensen 39188eea45cSKlaus Jensen #define TYPE_NVME "nvme" 39288eea45cSKlaus Jensen #define NVME(obj) \ 39388eea45cSKlaus Jensen OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) 39488eea45cSKlaus Jensen 39588eea45cSKlaus Jensen typedef struct NvmeParams { 39688eea45cSKlaus Jensen char *serial; 39788eea45cSKlaus Jensen uint32_t num_queues; /* deprecated since 5.1 */ 39888eea45cSKlaus Jensen uint32_t max_ioqpairs; 39988eea45cSKlaus Jensen uint16_t msix_qsize; 40088eea45cSKlaus Jensen uint32_t cmb_size_mb; 40188eea45cSKlaus Jensen uint8_t aerl; 40288eea45cSKlaus Jensen uint32_t aer_max_queued; 40388eea45cSKlaus Jensen uint8_t mdts; 40488eea45cSKlaus Jensen uint8_t vsl; 40588eea45cSKlaus Jensen bool use_intel_id; 40688eea45cSKlaus Jensen uint8_t zasl; 407cccc2651SNiklas Cassel bool auto_transition_zones; 40888eea45cSKlaus Jensen bool legacy_cmb; 409*44c2c094SLukasz Maniak uint8_t sriov_max_vfs; 41088eea45cSKlaus Jensen } NvmeParams; 41188eea45cSKlaus Jensen 41288eea45cSKlaus Jensen typedef struct NvmeCtrl { 41388eea45cSKlaus Jensen PCIDevice parent_obj; 41488eea45cSKlaus Jensen MemoryRegion bar0; 41588eea45cSKlaus Jensen MemoryRegion iomem; 41688eea45cSKlaus Jensen NvmeBar bar; 41788eea45cSKlaus Jensen NvmeParams params; 41888eea45cSKlaus Jensen NvmeBus bus; 41988eea45cSKlaus Jensen 42088eea45cSKlaus Jensen uint16_t cntlid; 42188eea45cSKlaus Jensen bool qs_created; 42288eea45cSKlaus Jensen uint32_t page_size; 42388eea45cSKlaus Jensen uint16_t page_bits; 42488eea45cSKlaus Jensen uint16_t max_prp_ents; 42588eea45cSKlaus Jensen uint16_t cqe_size; 42688eea45cSKlaus Jensen uint16_t sqe_size; 42788eea45cSKlaus Jensen uint32_t reg_size; 42888eea45cSKlaus Jensen uint32_t max_q_ents; 42988eea45cSKlaus Jensen uint8_t outstanding_aers; 43088eea45cSKlaus Jensen uint32_t irq_status; 43183d7ed5cSKlaus Jensen int cq_pending; 43288eea45cSKlaus Jensen uint64_t host_timestamp; /* Timestamp sent by the host */ 43388eea45cSKlaus Jensen uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ 43488eea45cSKlaus Jensen uint64_t starttime_ms; 43588eea45cSKlaus Jensen uint16_t temperature; 43688eea45cSKlaus Jensen uint8_t smart_critical_warning; 43788eea45cSKlaus Jensen 43888eea45cSKlaus Jensen struct { 43988eea45cSKlaus Jensen MemoryRegion mem; 44088eea45cSKlaus Jensen uint8_t *buf; 44188eea45cSKlaus Jensen bool cmse; 44288eea45cSKlaus Jensen hwaddr cba; 44388eea45cSKlaus Jensen } cmb; 44488eea45cSKlaus Jensen 44588eea45cSKlaus Jensen struct { 44688eea45cSKlaus Jensen HostMemoryBackend *dev; 44788eea45cSKlaus Jensen bool cmse; 44888eea45cSKlaus Jensen hwaddr cba; 44988eea45cSKlaus Jensen } pmr; 45088eea45cSKlaus Jensen 45188eea45cSKlaus Jensen uint8_t aer_mask; 45288eea45cSKlaus Jensen NvmeRequest **aer_reqs; 45388eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue; 45488eea45cSKlaus Jensen int aer_queued; 45588eea45cSKlaus Jensen 45688eea45cSKlaus Jensen uint32_t dmrsl; 45788eea45cSKlaus Jensen 45888eea45cSKlaus Jensen /* Namespace ID is started with 1 so bitmap should be 1-based */ 45988eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1) 46088eea45cSKlaus Jensen DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE); 46188eea45cSKlaus Jensen 46288eea45cSKlaus Jensen NvmeSubsystem *subsys; 46388eea45cSKlaus Jensen 46488eea45cSKlaus Jensen NvmeNamespace namespace; 46588eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 46688eea45cSKlaus Jensen NvmeSQueue **sq; 46788eea45cSKlaus Jensen NvmeCQueue **cq; 46888eea45cSKlaus Jensen NvmeSQueue admin_sq; 46988eea45cSKlaus Jensen NvmeCQueue admin_cq; 47088eea45cSKlaus Jensen NvmeIdCtrl id_ctrl; 47188eea45cSKlaus Jensen 47288eea45cSKlaus Jensen struct { 47388eea45cSKlaus Jensen struct { 47488eea45cSKlaus Jensen uint16_t temp_thresh_hi; 47588eea45cSKlaus Jensen uint16_t temp_thresh_low; 47688eea45cSKlaus Jensen }; 477d0c0697bSNaveen Nagar 47888eea45cSKlaus Jensen uint32_t async_config; 479d0c0697bSNaveen Nagar NvmeHostBehaviorSupport hbs; 48088eea45cSKlaus Jensen } features; 48188eea45cSKlaus Jensen } NvmeCtrl; 48288eea45cSKlaus Jensen 48388eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) 48488eea45cSKlaus Jensen { 48588eea45cSKlaus Jensen if (!nsid || nsid > NVME_MAX_NAMESPACES) { 48688eea45cSKlaus Jensen return NULL; 48788eea45cSKlaus Jensen } 48888eea45cSKlaus Jensen 48988eea45cSKlaus Jensen return n->namespaces[nsid]; 49088eea45cSKlaus Jensen } 49188eea45cSKlaus Jensen 49288eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req) 49388eea45cSKlaus Jensen { 49488eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 49588eea45cSKlaus Jensen NvmeCtrl *n = sq->ctrl; 49688eea45cSKlaus Jensen 49788eea45cSKlaus Jensen return n->cq[sq->cqid]; 49888eea45cSKlaus Jensen } 49988eea45cSKlaus Jensen 50088eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req) 50188eea45cSKlaus Jensen { 50288eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 50388eea45cSKlaus Jensen return sq->ctrl; 50488eea45cSKlaus Jensen } 50588eea45cSKlaus Jensen 50688eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req) 50788eea45cSKlaus Jensen { 50888eea45cSKlaus Jensen if (!req) { 50988eea45cSKlaus Jensen return 0xffff; 51088eea45cSKlaus Jensen } 51188eea45cSKlaus Jensen 51288eea45cSKlaus Jensen return le16_to_cpu(req->cqe.cid); 51388eea45cSKlaus Jensen } 51488eea45cSKlaus Jensen 51588eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); 5168d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len, 51788eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 5188d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_mdata(NvmeCtrl *n, void *ptr, uint32_t len, 51988eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 52088eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret); 52188eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, 52288eea45cSKlaus Jensen NvmeCmd *cmd); 52388eea45cSKlaus Jensen 52452581c71SMarkus Armbruster #endif /* HW_NVME_NVME_H */ 525