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 1888eea45cSKlaus Jensen #ifndef HW_NVME_INTERNAL_H 1988eea45cSKlaus Jensen #define HW_NVME_INTERNAL_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 2788eea45cSKlaus Jensen #define NVME_MAX_CONTROLLERS 32 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]; 5188eea45cSKlaus Jensen 5288eea45cSKlaus Jensen NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; 5388eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 5488eea45cSKlaus Jensen 5588eea45cSKlaus Jensen struct { 5688eea45cSKlaus Jensen char *nqn; 5788eea45cSKlaus Jensen } params; 5888eea45cSKlaus Jensen } NvmeSubsystem; 5988eea45cSKlaus Jensen 6088eea45cSKlaus Jensen int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp); 61b0fde9e8SKlaus Jensen void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n); 6288eea45cSKlaus Jensen 6388eea45cSKlaus Jensen static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys, 6488eea45cSKlaus Jensen uint32_t cntlid) 6588eea45cSKlaus Jensen { 6688eea45cSKlaus Jensen if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) { 6788eea45cSKlaus Jensen return NULL; 6888eea45cSKlaus Jensen } 6988eea45cSKlaus Jensen 7088eea45cSKlaus Jensen return subsys->ctrls[cntlid]; 7188eea45cSKlaus Jensen } 7288eea45cSKlaus Jensen 7388eea45cSKlaus Jensen static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys, 7488eea45cSKlaus Jensen uint32_t nsid) 7588eea45cSKlaus Jensen { 7688eea45cSKlaus Jensen if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) { 7788eea45cSKlaus Jensen return NULL; 7888eea45cSKlaus Jensen } 7988eea45cSKlaus Jensen 8088eea45cSKlaus Jensen return subsys->namespaces[nsid]; 8188eea45cSKlaus Jensen } 8288eea45cSKlaus Jensen 8388eea45cSKlaus Jensen #define TYPE_NVME_NS "nvme-ns" 8488eea45cSKlaus Jensen #define NVME_NS(obj) \ 8588eea45cSKlaus Jensen OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) 8688eea45cSKlaus Jensen 8788eea45cSKlaus Jensen typedef struct NvmeZone { 8888eea45cSKlaus Jensen NvmeZoneDescr d; 8988eea45cSKlaus Jensen uint64_t w_ptr; 9088eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeZone) entry; 9188eea45cSKlaus Jensen } NvmeZone; 9288eea45cSKlaus Jensen 9388eea45cSKlaus Jensen typedef struct NvmeNamespaceParams { 9488eea45cSKlaus Jensen bool detached; 9588eea45cSKlaus Jensen bool shared; 9688eea45cSKlaus Jensen uint32_t nsid; 9788eea45cSKlaus Jensen QemuUUID uuid; 986870cfb8SHeinrich Schuchardt uint64_t eui64; 993276dde4SHeinrich Schuchardt bool eui64_default; 10088eea45cSKlaus Jensen 10188eea45cSKlaus Jensen uint16_t ms; 10288eea45cSKlaus Jensen uint8_t mset; 10388eea45cSKlaus Jensen uint8_t pi; 10488eea45cSKlaus Jensen uint8_t pil; 10588eea45cSKlaus Jensen 10688eea45cSKlaus Jensen uint16_t mssrl; 10788eea45cSKlaus Jensen uint32_t mcl; 10888eea45cSKlaus Jensen uint8_t msrc; 10988eea45cSKlaus Jensen 11088eea45cSKlaus Jensen bool zoned; 11188eea45cSKlaus Jensen bool cross_zone_read; 11288eea45cSKlaus Jensen uint64_t zone_size_bs; 11388eea45cSKlaus Jensen uint64_t zone_cap_bs; 11488eea45cSKlaus Jensen uint32_t max_active_zones; 11588eea45cSKlaus Jensen uint32_t max_open_zones; 11688eea45cSKlaus Jensen uint32_t zd_extension_size; 117*e321b4cdSKlaus Jensen 118*e321b4cdSKlaus Jensen uint32_t numzrwa; 119*e321b4cdSKlaus Jensen uint64_t zrwas; 120*e321b4cdSKlaus Jensen uint64_t zrwafg; 12188eea45cSKlaus Jensen } NvmeNamespaceParams; 12288eea45cSKlaus Jensen 12388eea45cSKlaus Jensen typedef struct NvmeNamespace { 12488eea45cSKlaus Jensen DeviceState parent_obj; 12588eea45cSKlaus Jensen BlockConf blkconf; 12688eea45cSKlaus Jensen int32_t bootindex; 12788eea45cSKlaus Jensen int64_t size; 12888eea45cSKlaus Jensen int64_t moff; 12988eea45cSKlaus Jensen NvmeIdNs id_ns; 13088eea45cSKlaus Jensen NvmeLBAF lbaf; 13188eea45cSKlaus Jensen size_t lbasz; 13288eea45cSKlaus Jensen const uint32_t *iocs; 13388eea45cSKlaus Jensen uint8_t csi; 13488eea45cSKlaus Jensen uint16_t status; 13588eea45cSKlaus Jensen int attached; 13688eea45cSKlaus Jensen 137*e321b4cdSKlaus Jensen struct { 138*e321b4cdSKlaus Jensen uint16_t zrwas; 139*e321b4cdSKlaus Jensen uint16_t zrwafg; 140*e321b4cdSKlaus Jensen uint32_t numzrwa; 141*e321b4cdSKlaus Jensen } zns; 142*e321b4cdSKlaus Jensen 14388eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeNamespace) entry; 14488eea45cSKlaus Jensen 14588eea45cSKlaus Jensen NvmeIdNsZoned *id_ns_zoned; 14688eea45cSKlaus Jensen NvmeZone *zone_array; 14788eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) exp_open_zones; 14888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) imp_open_zones; 14988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) closed_zones; 15088eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) full_zones; 15188eea45cSKlaus Jensen uint32_t num_zones; 15288eea45cSKlaus Jensen uint64_t zone_size; 15388eea45cSKlaus Jensen uint64_t zone_capacity; 15488eea45cSKlaus Jensen uint32_t zone_size_log2; 15588eea45cSKlaus Jensen uint8_t *zd_extensions; 15688eea45cSKlaus Jensen int32_t nr_open_zones; 15788eea45cSKlaus Jensen int32_t nr_active_zones; 15888eea45cSKlaus Jensen 15988eea45cSKlaus Jensen NvmeNamespaceParams params; 16088eea45cSKlaus Jensen 16188eea45cSKlaus Jensen struct { 16288eea45cSKlaus Jensen uint32_t err_rec; 16388eea45cSKlaus Jensen } features; 16488eea45cSKlaus Jensen } NvmeNamespace; 16588eea45cSKlaus Jensen 16688eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns) 16788eea45cSKlaus Jensen { 16888eea45cSKlaus Jensen if (ns) { 16988eea45cSKlaus Jensen return ns->params.nsid; 17088eea45cSKlaus Jensen } 17188eea45cSKlaus Jensen 17288eea45cSKlaus Jensen return 0; 17388eea45cSKlaus Jensen } 17488eea45cSKlaus Jensen 17588eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) 17688eea45cSKlaus Jensen { 17788eea45cSKlaus Jensen return lba << ns->lbaf.ds; 17888eea45cSKlaus Jensen } 17988eea45cSKlaus Jensen 18088eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba) 18188eea45cSKlaus Jensen { 18288eea45cSKlaus Jensen return ns->lbaf.ms * lba; 18388eea45cSKlaus Jensen } 18488eea45cSKlaus Jensen 18588eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba) 18688eea45cSKlaus Jensen { 18788eea45cSKlaus Jensen return ns->moff + nvme_m2b(ns, lba); 18888eea45cSKlaus Jensen } 18988eea45cSKlaus Jensen 19088eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns) 19188eea45cSKlaus Jensen { 19288eea45cSKlaus Jensen return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas); 19388eea45cSKlaus Jensen } 19488eea45cSKlaus Jensen 19588eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone) 19688eea45cSKlaus Jensen { 19788eea45cSKlaus Jensen return zone->d.zs >> 4; 19888eea45cSKlaus Jensen } 19988eea45cSKlaus Jensen 20088eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state) 20188eea45cSKlaus Jensen { 20288eea45cSKlaus Jensen zone->d.zs = state << 4; 20388eea45cSKlaus Jensen } 20488eea45cSKlaus Jensen 20588eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone) 20688eea45cSKlaus Jensen { 20788eea45cSKlaus Jensen return zone->d.zslba + ns->zone_size; 20888eea45cSKlaus Jensen } 20988eea45cSKlaus Jensen 21088eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone) 21188eea45cSKlaus Jensen { 21288eea45cSKlaus Jensen return zone->d.zslba + zone->d.zcap; 21388eea45cSKlaus Jensen } 21488eea45cSKlaus Jensen 21588eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone) 21688eea45cSKlaus Jensen { 21788eea45cSKlaus Jensen uint8_t st = nvme_get_zone_state(zone); 21888eea45cSKlaus Jensen 21988eea45cSKlaus Jensen return st != NVME_ZONE_STATE_FULL && 22088eea45cSKlaus Jensen st != NVME_ZONE_STATE_READ_ONLY && 22188eea45cSKlaus Jensen st != NVME_ZONE_STATE_OFFLINE; 22288eea45cSKlaus Jensen } 22388eea45cSKlaus Jensen 22488eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns, 22588eea45cSKlaus Jensen uint32_t zone_idx) 22688eea45cSKlaus Jensen { 22788eea45cSKlaus Jensen return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; 22888eea45cSKlaus Jensen } 22988eea45cSKlaus Jensen 23088eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns) 23188eea45cSKlaus Jensen { 23288eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 23388eea45cSKlaus Jensen if (ns->params.max_open_zones) { 23488eea45cSKlaus Jensen ns->nr_open_zones++; 23588eea45cSKlaus Jensen assert(ns->nr_open_zones <= ns->params.max_open_zones); 23688eea45cSKlaus Jensen } 23788eea45cSKlaus Jensen } 23888eea45cSKlaus Jensen 23988eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns) 24088eea45cSKlaus Jensen { 24188eea45cSKlaus Jensen if (ns->params.max_open_zones) { 24288eea45cSKlaus Jensen assert(ns->nr_open_zones > 0); 24388eea45cSKlaus Jensen ns->nr_open_zones--; 24488eea45cSKlaus Jensen } 24588eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 24688eea45cSKlaus Jensen } 24788eea45cSKlaus Jensen 24888eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns) 24988eea45cSKlaus Jensen { 25088eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 25188eea45cSKlaus Jensen if (ns->params.max_active_zones) { 25288eea45cSKlaus Jensen ns->nr_active_zones++; 25388eea45cSKlaus Jensen assert(ns->nr_active_zones <= ns->params.max_active_zones); 25488eea45cSKlaus Jensen } 25588eea45cSKlaus Jensen } 25688eea45cSKlaus Jensen 25788eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns) 25888eea45cSKlaus Jensen { 25988eea45cSKlaus Jensen if (ns->params.max_active_zones) { 26088eea45cSKlaus Jensen assert(ns->nr_active_zones > 0); 26188eea45cSKlaus Jensen ns->nr_active_zones--; 26288eea45cSKlaus Jensen assert(ns->nr_active_zones >= ns->nr_open_zones); 26388eea45cSKlaus Jensen } 26488eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 26588eea45cSKlaus Jensen } 26688eea45cSKlaus Jensen 26788eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns); 2685e4f6bccSKlaus Jensen int nvme_ns_setup(NvmeNamespace *ns, Error **errp); 26988eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns); 27088eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns); 27188eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns); 27288eea45cSKlaus Jensen 27388eea45cSKlaus Jensen typedef struct NvmeAsyncEvent { 27488eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeAsyncEvent) entry; 27588eea45cSKlaus Jensen NvmeAerResult result; 27688eea45cSKlaus Jensen } NvmeAsyncEvent; 27788eea45cSKlaus Jensen 27888eea45cSKlaus Jensen enum { 27988eea45cSKlaus Jensen NVME_SG_ALLOC = 1 << 0, 28088eea45cSKlaus Jensen NVME_SG_DMA = 1 << 1, 28188eea45cSKlaus Jensen }; 28288eea45cSKlaus Jensen 28388eea45cSKlaus Jensen typedef struct NvmeSg { 28488eea45cSKlaus Jensen int flags; 28588eea45cSKlaus Jensen 28688eea45cSKlaus Jensen union { 28788eea45cSKlaus Jensen QEMUSGList qsg; 28888eea45cSKlaus Jensen QEMUIOVector iov; 28988eea45cSKlaus Jensen }; 29088eea45cSKlaus Jensen } NvmeSg; 29188eea45cSKlaus Jensen 29288eea45cSKlaus Jensen typedef enum NvmeTxDirection { 29388eea45cSKlaus Jensen NVME_TX_DIRECTION_TO_DEVICE = 0, 29488eea45cSKlaus Jensen NVME_TX_DIRECTION_FROM_DEVICE = 1, 29588eea45cSKlaus Jensen } NvmeTxDirection; 29688eea45cSKlaus Jensen 29788eea45cSKlaus Jensen typedef struct NvmeRequest { 29888eea45cSKlaus Jensen struct NvmeSQueue *sq; 29988eea45cSKlaus Jensen struct NvmeNamespace *ns; 30088eea45cSKlaus Jensen BlockAIOCB *aiocb; 30188eea45cSKlaus Jensen uint16_t status; 30288eea45cSKlaus Jensen void *opaque; 30388eea45cSKlaus Jensen NvmeCqe cqe; 30488eea45cSKlaus Jensen NvmeCmd cmd; 30588eea45cSKlaus Jensen BlockAcctCookie acct; 30688eea45cSKlaus Jensen NvmeSg sg; 30788eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeRequest)entry; 30888eea45cSKlaus Jensen } NvmeRequest; 30988eea45cSKlaus Jensen 31088eea45cSKlaus Jensen typedef struct NvmeBounceContext { 31188eea45cSKlaus Jensen NvmeRequest *req; 31288eea45cSKlaus Jensen 31388eea45cSKlaus Jensen struct { 31488eea45cSKlaus Jensen QEMUIOVector iov; 31588eea45cSKlaus Jensen uint8_t *bounce; 31688eea45cSKlaus Jensen } data, mdata; 31788eea45cSKlaus Jensen } NvmeBounceContext; 31888eea45cSKlaus Jensen 31988eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc) 32088eea45cSKlaus Jensen { 32188eea45cSKlaus Jensen switch (opc) { 32288eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ"; 32388eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ"; 32488eea45cSKlaus Jensen case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE"; 32588eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ"; 32688eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ"; 32788eea45cSKlaus Jensen case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY"; 32888eea45cSKlaus Jensen case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT"; 32988eea45cSKlaus Jensen case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES"; 33088eea45cSKlaus Jensen case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES"; 33188eea45cSKlaus Jensen case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ"; 33288eea45cSKlaus Jensen case NVME_ADM_CMD_NS_ATTACHMENT: return "NVME_ADM_CMD_NS_ATTACHMENT"; 33388eea45cSKlaus Jensen case NVME_ADM_CMD_FORMAT_NVM: return "NVME_ADM_CMD_FORMAT_NVM"; 33488eea45cSKlaus Jensen default: return "NVME_ADM_CMD_UNKNOWN"; 33588eea45cSKlaus Jensen } 33688eea45cSKlaus Jensen } 33788eea45cSKlaus Jensen 33888eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc) 33988eea45cSKlaus Jensen { 34088eea45cSKlaus Jensen switch (opc) { 34188eea45cSKlaus Jensen case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH"; 34288eea45cSKlaus Jensen case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE"; 34388eea45cSKlaus Jensen case NVME_CMD_READ: return "NVME_NVM_CMD_READ"; 34488eea45cSKlaus Jensen case NVME_CMD_COMPARE: return "NVME_NVM_CMD_COMPARE"; 34588eea45cSKlaus Jensen case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES"; 34688eea45cSKlaus Jensen case NVME_CMD_DSM: return "NVME_NVM_CMD_DSM"; 34788eea45cSKlaus Jensen case NVME_CMD_VERIFY: return "NVME_NVM_CMD_VERIFY"; 34888eea45cSKlaus Jensen case NVME_CMD_COPY: return "NVME_NVM_CMD_COPY"; 34988eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND"; 35088eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV"; 35188eea45cSKlaus Jensen case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND"; 35288eea45cSKlaus Jensen default: return "NVME_NVM_CMD_UNKNOWN"; 35388eea45cSKlaus Jensen } 35488eea45cSKlaus Jensen } 35588eea45cSKlaus Jensen 35688eea45cSKlaus Jensen typedef struct NvmeSQueue { 35788eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 35888eea45cSKlaus Jensen uint16_t sqid; 35988eea45cSKlaus Jensen uint16_t cqid; 36088eea45cSKlaus Jensen uint32_t head; 36188eea45cSKlaus Jensen uint32_t tail; 36288eea45cSKlaus Jensen uint32_t size; 36388eea45cSKlaus Jensen uint64_t dma_addr; 36488eea45cSKlaus Jensen QEMUTimer *timer; 36588eea45cSKlaus Jensen NvmeRequest *io_req; 36688eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 36788eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) out_req_list; 36888eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeSQueue) entry; 36988eea45cSKlaus Jensen } NvmeSQueue; 37088eea45cSKlaus Jensen 37188eea45cSKlaus Jensen typedef struct NvmeCQueue { 37288eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 37388eea45cSKlaus Jensen uint8_t phase; 37488eea45cSKlaus Jensen uint16_t cqid; 37588eea45cSKlaus Jensen uint16_t irq_enabled; 37688eea45cSKlaus Jensen uint32_t head; 37788eea45cSKlaus Jensen uint32_t tail; 37888eea45cSKlaus Jensen uint32_t vector; 37988eea45cSKlaus Jensen uint32_t size; 38088eea45cSKlaus Jensen uint64_t dma_addr; 38188eea45cSKlaus Jensen QEMUTimer *timer; 38288eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeSQueue) sq_list; 38388eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 38488eea45cSKlaus Jensen } NvmeCQueue; 38588eea45cSKlaus Jensen 38688eea45cSKlaus Jensen #define TYPE_NVME "nvme" 38788eea45cSKlaus Jensen #define NVME(obj) \ 38888eea45cSKlaus Jensen OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) 38988eea45cSKlaus Jensen 39088eea45cSKlaus Jensen typedef struct NvmeParams { 39188eea45cSKlaus Jensen char *serial; 39288eea45cSKlaus Jensen uint32_t num_queues; /* deprecated since 5.1 */ 39388eea45cSKlaus Jensen uint32_t max_ioqpairs; 39488eea45cSKlaus Jensen uint16_t msix_qsize; 39588eea45cSKlaus Jensen uint32_t cmb_size_mb; 39688eea45cSKlaus Jensen uint8_t aerl; 39788eea45cSKlaus Jensen uint32_t aer_max_queued; 39888eea45cSKlaus Jensen uint8_t mdts; 39988eea45cSKlaus Jensen uint8_t vsl; 40088eea45cSKlaus Jensen bool use_intel_id; 40188eea45cSKlaus Jensen uint8_t zasl; 402cccc2651SNiklas Cassel bool auto_transition_zones; 40388eea45cSKlaus Jensen bool legacy_cmb; 40488eea45cSKlaus Jensen } NvmeParams; 40588eea45cSKlaus Jensen 40688eea45cSKlaus Jensen typedef struct NvmeCtrl { 40788eea45cSKlaus Jensen PCIDevice parent_obj; 40888eea45cSKlaus Jensen MemoryRegion bar0; 40988eea45cSKlaus Jensen MemoryRegion iomem; 41088eea45cSKlaus Jensen NvmeBar bar; 41188eea45cSKlaus Jensen NvmeParams params; 41288eea45cSKlaus Jensen NvmeBus bus; 41388eea45cSKlaus Jensen 41488eea45cSKlaus Jensen uint16_t cntlid; 41588eea45cSKlaus Jensen bool qs_created; 41688eea45cSKlaus Jensen uint32_t page_size; 41788eea45cSKlaus Jensen uint16_t page_bits; 41888eea45cSKlaus Jensen uint16_t max_prp_ents; 41988eea45cSKlaus Jensen uint16_t cqe_size; 42088eea45cSKlaus Jensen uint16_t sqe_size; 42188eea45cSKlaus Jensen uint32_t reg_size; 42288eea45cSKlaus Jensen uint32_t max_q_ents; 42388eea45cSKlaus Jensen uint8_t outstanding_aers; 42488eea45cSKlaus Jensen uint32_t irq_status; 42583d7ed5cSKlaus Jensen int cq_pending; 42688eea45cSKlaus Jensen uint64_t host_timestamp; /* Timestamp sent by the host */ 42788eea45cSKlaus Jensen uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ 42888eea45cSKlaus Jensen uint64_t starttime_ms; 42988eea45cSKlaus Jensen uint16_t temperature; 43088eea45cSKlaus Jensen uint8_t smart_critical_warning; 43188eea45cSKlaus Jensen 43288eea45cSKlaus Jensen struct { 43388eea45cSKlaus Jensen MemoryRegion mem; 43488eea45cSKlaus Jensen uint8_t *buf; 43588eea45cSKlaus Jensen bool cmse; 43688eea45cSKlaus Jensen hwaddr cba; 43788eea45cSKlaus Jensen } cmb; 43888eea45cSKlaus Jensen 43988eea45cSKlaus Jensen struct { 44088eea45cSKlaus Jensen HostMemoryBackend *dev; 44188eea45cSKlaus Jensen bool cmse; 44288eea45cSKlaus Jensen hwaddr cba; 44388eea45cSKlaus Jensen } pmr; 44488eea45cSKlaus Jensen 44588eea45cSKlaus Jensen uint8_t aer_mask; 44688eea45cSKlaus Jensen NvmeRequest **aer_reqs; 44788eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue; 44888eea45cSKlaus Jensen int aer_queued; 44988eea45cSKlaus Jensen 45088eea45cSKlaus Jensen uint32_t dmrsl; 45188eea45cSKlaus Jensen 45288eea45cSKlaus Jensen /* Namespace ID is started with 1 so bitmap should be 1-based */ 45388eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1) 45488eea45cSKlaus Jensen DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE); 45588eea45cSKlaus Jensen 45688eea45cSKlaus Jensen NvmeSubsystem *subsys; 45788eea45cSKlaus Jensen 45888eea45cSKlaus Jensen NvmeNamespace namespace; 45988eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 46088eea45cSKlaus Jensen NvmeSQueue **sq; 46188eea45cSKlaus Jensen NvmeCQueue **cq; 46288eea45cSKlaus Jensen NvmeSQueue admin_sq; 46388eea45cSKlaus Jensen NvmeCQueue admin_cq; 46488eea45cSKlaus Jensen NvmeIdCtrl id_ctrl; 46588eea45cSKlaus Jensen 46688eea45cSKlaus Jensen struct { 46788eea45cSKlaus Jensen struct { 46888eea45cSKlaus Jensen uint16_t temp_thresh_hi; 46988eea45cSKlaus Jensen uint16_t temp_thresh_low; 47088eea45cSKlaus Jensen }; 47188eea45cSKlaus Jensen uint32_t async_config; 47288eea45cSKlaus Jensen } features; 47388eea45cSKlaus Jensen } NvmeCtrl; 47488eea45cSKlaus Jensen 47588eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) 47688eea45cSKlaus Jensen { 47788eea45cSKlaus Jensen if (!nsid || nsid > NVME_MAX_NAMESPACES) { 47888eea45cSKlaus Jensen return NULL; 47988eea45cSKlaus Jensen } 48088eea45cSKlaus Jensen 48188eea45cSKlaus Jensen return n->namespaces[nsid]; 48288eea45cSKlaus Jensen } 48388eea45cSKlaus Jensen 48488eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req) 48588eea45cSKlaus Jensen { 48688eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 48788eea45cSKlaus Jensen NvmeCtrl *n = sq->ctrl; 48888eea45cSKlaus Jensen 48988eea45cSKlaus Jensen return n->cq[sq->cqid]; 49088eea45cSKlaus Jensen } 49188eea45cSKlaus Jensen 49288eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req) 49388eea45cSKlaus Jensen { 49488eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 49588eea45cSKlaus Jensen return sq->ctrl; 49688eea45cSKlaus Jensen } 49788eea45cSKlaus Jensen 49888eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req) 49988eea45cSKlaus Jensen { 50088eea45cSKlaus Jensen if (!req) { 50188eea45cSKlaus Jensen return 0xffff; 50288eea45cSKlaus Jensen } 50388eea45cSKlaus Jensen 50488eea45cSKlaus Jensen return le16_to_cpu(req->cqe.cid); 50588eea45cSKlaus Jensen } 50688eea45cSKlaus Jensen 50788eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); 5088d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len, 50988eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 5108d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_mdata(NvmeCtrl *n, void *ptr, uint32_t len, 51188eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 51288eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret); 51388eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, 51488eea45cSKlaus Jensen NvmeCmd *cmd); 51588eea45cSKlaus Jensen 51688eea45cSKlaus Jensen /* from Linux kernel (crypto/crct10dif_common.c) */ 51788eea45cSKlaus Jensen static const uint16_t t10_dif_crc_table[256] = { 51888eea45cSKlaus Jensen 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, 51988eea45cSKlaus Jensen 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, 52088eea45cSKlaus Jensen 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, 52188eea45cSKlaus Jensen 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, 52288eea45cSKlaus Jensen 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, 52388eea45cSKlaus Jensen 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, 52488eea45cSKlaus Jensen 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, 52588eea45cSKlaus Jensen 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, 52688eea45cSKlaus Jensen 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, 52788eea45cSKlaus Jensen 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, 52888eea45cSKlaus Jensen 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, 52988eea45cSKlaus Jensen 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, 53088eea45cSKlaus Jensen 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, 53188eea45cSKlaus Jensen 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, 53288eea45cSKlaus Jensen 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, 53388eea45cSKlaus Jensen 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, 53488eea45cSKlaus Jensen 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, 53588eea45cSKlaus Jensen 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, 53688eea45cSKlaus Jensen 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, 53788eea45cSKlaus Jensen 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, 53888eea45cSKlaus Jensen 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, 53988eea45cSKlaus Jensen 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, 54088eea45cSKlaus Jensen 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, 54188eea45cSKlaus Jensen 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, 54288eea45cSKlaus Jensen 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, 54388eea45cSKlaus Jensen 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, 54488eea45cSKlaus Jensen 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, 54588eea45cSKlaus Jensen 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, 54688eea45cSKlaus Jensen 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, 54788eea45cSKlaus Jensen 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, 54888eea45cSKlaus Jensen 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, 54988eea45cSKlaus Jensen 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 55088eea45cSKlaus Jensen }; 55188eea45cSKlaus Jensen 5522a132309SKlaus Jensen uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, 55388eea45cSKlaus Jensen uint32_t reftag); 55488eea45cSKlaus Jensen uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, 55588eea45cSKlaus Jensen uint64_t slba); 55688eea45cSKlaus Jensen void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, 55788eea45cSKlaus Jensen uint8_t *mbuf, size_t mlen, uint16_t apptag, 5580ca5c3ccSKlaus Jensen uint32_t *reftag); 55988eea45cSKlaus Jensen uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, 5602a132309SKlaus Jensen uint8_t *mbuf, size_t mlen, uint8_t prinfo, 56188eea45cSKlaus Jensen uint64_t slba, uint16_t apptag, 5620ca5c3ccSKlaus Jensen uint16_t appmask, uint32_t *reftag); 56388eea45cSKlaus Jensen uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req); 56488eea45cSKlaus Jensen 56588eea45cSKlaus Jensen 56688eea45cSKlaus Jensen #endif /* HW_NVME_INTERNAL_H */ 567