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" 22edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h" 2388eea45cSKlaus Jensen #include "hw/block/block.h" 2488eea45cSKlaus Jensen 2588eea45cSKlaus Jensen #include "block/nvme.h" 2688eea45cSKlaus Jensen 2744c2c094SLukasz Maniak #define NVME_MAX_CONTROLLERS 256 2888eea45cSKlaus Jensen #define NVME_MAX_NAMESPACES 256 293276dde4SHeinrich Schuchardt #define NVME_EUI64_DEFAULT ((uint64_t)0x5254000000000000) 3073064edfSJesper Devantier #define NVME_FDP_MAX_EVENTS 63 3173064edfSJesper Devantier #define NVME_FDP_MAXPIDS 128 3288eea45cSKlaus Jensen 336a33f2e9SKlaus Jensen /* 346a33f2e9SKlaus Jensen * The controller only supports Submission and Completion Queue Entry Sizes of 356a33f2e9SKlaus Jensen * 64 and 16 bytes respectively. 366a33f2e9SKlaus Jensen */ 376a33f2e9SKlaus Jensen #define NVME_SQES 6 386a33f2e9SKlaus Jensen #define NVME_CQES 4 396a33f2e9SKlaus Jensen 4038f4ac65SKlaus Jensen QEMU_BUILD_BUG_ON(NVME_MAX_NAMESPACES > NVME_NSID_BROADCAST - 1); 4138f4ac65SKlaus Jensen 4288eea45cSKlaus Jensen typedef struct NvmeCtrl NvmeCtrl; 4388eea45cSKlaus Jensen typedef struct NvmeNamespace NvmeNamespace; 4488eea45cSKlaus Jensen 455ffbaeedSKlaus Jensen #define TYPE_NVME_BUS "nvme-bus" 465ffbaeedSKlaus Jensen OBJECT_DECLARE_SIMPLE_TYPE(NvmeBus, NVME_BUS) 475ffbaeedSKlaus Jensen 485ffbaeedSKlaus Jensen typedef struct NvmeBus { 495ffbaeedSKlaus Jensen BusState parent_bus; 505ffbaeedSKlaus Jensen } NvmeBus; 515ffbaeedSKlaus Jensen 5288eea45cSKlaus Jensen #define TYPE_NVME_SUBSYS "nvme-subsys" 5388eea45cSKlaus Jensen #define NVME_SUBSYS(obj) \ 5488eea45cSKlaus Jensen OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS) 5599f48ae7SLukasz Maniak #define SUBSYS_SLOT_RSVD (void *)0xFFFF 5688eea45cSKlaus Jensen 5773064edfSJesper Devantier typedef struct NvmeReclaimUnit { 5873064edfSJesper Devantier uint64_t ruamw; 5973064edfSJesper Devantier } NvmeReclaimUnit; 6073064edfSJesper Devantier 6173064edfSJesper Devantier typedef struct NvmeRuHandle { 6273064edfSJesper Devantier uint8_t ruht; 6373064edfSJesper Devantier uint8_t ruha; 6473064edfSJesper Devantier uint64_t event_filter; 6573064edfSJesper Devantier uint8_t lbafi; 6673064edfSJesper Devantier uint64_t ruamw; 6773064edfSJesper Devantier 6873064edfSJesper Devantier /* reclaim units indexed by reclaim group */ 6973064edfSJesper Devantier NvmeReclaimUnit *rus; 7073064edfSJesper Devantier } NvmeRuHandle; 7173064edfSJesper Devantier 7273064edfSJesper Devantier typedef struct NvmeFdpEventBuffer { 7373064edfSJesper Devantier NvmeFdpEvent events[NVME_FDP_MAX_EVENTS]; 7473064edfSJesper Devantier unsigned int nelems; 7573064edfSJesper Devantier unsigned int start; 7673064edfSJesper Devantier unsigned int next; 7773064edfSJesper Devantier } NvmeFdpEventBuffer; 7873064edfSJesper Devantier 79771dbc3aSKlaus Jensen typedef struct NvmeEnduranceGroup { 80771dbc3aSKlaus Jensen uint8_t event_conf; 8173064edfSJesper Devantier 8273064edfSJesper Devantier struct { 8373064edfSJesper Devantier NvmeFdpEventBuffer host_events, ctrl_events; 8473064edfSJesper Devantier 8573064edfSJesper Devantier uint16_t nruh; 8673064edfSJesper Devantier uint16_t nrg; 8773064edfSJesper Devantier uint8_t rgif; 8873064edfSJesper Devantier uint64_t runs; 8973064edfSJesper Devantier 9073064edfSJesper Devantier uint64_t hbmw; 9173064edfSJesper Devantier uint64_t mbmw; 9273064edfSJesper Devantier uint64_t mbe; 9373064edfSJesper Devantier 9473064edfSJesper Devantier bool enabled; 9573064edfSJesper Devantier 9673064edfSJesper Devantier NvmeRuHandle *ruhs; 9773064edfSJesper Devantier } fdp; 98771dbc3aSKlaus Jensen } NvmeEnduranceGroup; 99771dbc3aSKlaus Jensen 10088eea45cSKlaus Jensen typedef struct NvmeSubsystem { 10188eea45cSKlaus Jensen DeviceState parent_obj; 1025ffbaeedSKlaus Jensen NvmeBus bus; 10388eea45cSKlaus Jensen uint8_t subnqn[256]; 104a859eb9fSKlaus Jensen char *serial; 10588eea45cSKlaus Jensen 10688eea45cSKlaus Jensen NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; 10788eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 10873064edfSJesper Devantier NvmeEnduranceGroup endgrp; 10988eea45cSKlaus Jensen 11088eea45cSKlaus Jensen struct { 11188eea45cSKlaus Jensen char *nqn; 11273064edfSJesper Devantier 11373064edfSJesper Devantier struct { 11473064edfSJesper Devantier bool enabled; 11573064edfSJesper Devantier uint64_t runs; 11673064edfSJesper Devantier uint16_t nruh; 11773064edfSJesper Devantier uint32_t nrg; 11873064edfSJesper Devantier } fdp; 11988eea45cSKlaus Jensen } params; 12088eea45cSKlaus Jensen } NvmeSubsystem; 12188eea45cSKlaus Jensen 12288eea45cSKlaus Jensen int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp); 123b0fde9e8SKlaus Jensen void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n); 12488eea45cSKlaus Jensen 12588eea45cSKlaus Jensen static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys, 12688eea45cSKlaus Jensen uint32_t cntlid) 12788eea45cSKlaus Jensen { 12888eea45cSKlaus Jensen if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) { 12988eea45cSKlaus Jensen return NULL; 13088eea45cSKlaus Jensen } 13188eea45cSKlaus Jensen 13299f48ae7SLukasz Maniak if (subsys->ctrls[cntlid] == SUBSYS_SLOT_RSVD) { 13399f48ae7SLukasz Maniak return NULL; 13499f48ae7SLukasz Maniak } 13599f48ae7SLukasz Maniak 13688eea45cSKlaus Jensen return subsys->ctrls[cntlid]; 13788eea45cSKlaus Jensen } 13888eea45cSKlaus Jensen 13988eea45cSKlaus Jensen static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys, 14088eea45cSKlaus Jensen uint32_t nsid) 14188eea45cSKlaus Jensen { 14288eea45cSKlaus Jensen if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) { 14388eea45cSKlaus Jensen return NULL; 14488eea45cSKlaus Jensen } 14588eea45cSKlaus Jensen 14688eea45cSKlaus Jensen return subsys->namespaces[nsid]; 14788eea45cSKlaus Jensen } 14888eea45cSKlaus Jensen 14988eea45cSKlaus Jensen #define TYPE_NVME_NS "nvme-ns" 15088eea45cSKlaus Jensen #define NVME_NS(obj) \ 15188eea45cSKlaus Jensen OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) 15288eea45cSKlaus Jensen 15388eea45cSKlaus Jensen typedef struct NvmeZone { 15488eea45cSKlaus Jensen NvmeZoneDescr d; 15588eea45cSKlaus Jensen uint64_t w_ptr; 15688eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeZone) entry; 15788eea45cSKlaus Jensen } NvmeZone; 15888eea45cSKlaus Jensen 15973064edfSJesper Devantier #define FDP_EVT_MAX 0xff 16073064edfSJesper Devantier #define NVME_FDP_MAX_NS_RUHS 32u 16173064edfSJesper Devantier #define FDPVSS 0 16273064edfSJesper Devantier 16373064edfSJesper Devantier static const uint8_t nvme_fdp_evf_shifts[FDP_EVT_MAX] = { 16473064edfSJesper Devantier /* Host events */ 16573064edfSJesper Devantier [FDP_EVT_RU_NOT_FULLY_WRITTEN] = 0, 16673064edfSJesper Devantier [FDP_EVT_RU_ATL_EXCEEDED] = 1, 16773064edfSJesper Devantier [FDP_EVT_CTRL_RESET_RUH] = 2, 16873064edfSJesper Devantier [FDP_EVT_INVALID_PID] = 3, 16973064edfSJesper Devantier /* CTRL events */ 17073064edfSJesper Devantier [FDP_EVT_MEDIA_REALLOC] = 32, 17173064edfSJesper Devantier [FDP_EVT_RUH_IMPLICIT_RU_CHANGE] = 33, 17273064edfSJesper Devantier }; 17373064edfSJesper Devantier 174bdc31646SRoque Arcudia Hernandez #define NGUID_LEN 16 175bdc31646SRoque Arcudia Hernandez 176bdc31646SRoque Arcudia Hernandez typedef struct { 177bdc31646SRoque Arcudia Hernandez uint8_t data[NGUID_LEN]; 178bdc31646SRoque Arcudia Hernandez } NvmeNGUID; 179bdc31646SRoque Arcudia Hernandez 180bdc31646SRoque Arcudia Hernandez bool nvme_nguid_is_null(const NvmeNGUID *nguid); 181bdc31646SRoque Arcudia Hernandez 182bdc31646SRoque Arcudia Hernandez extern const PropertyInfo qdev_prop_nguid; 183bdc31646SRoque Arcudia Hernandez 184bdc31646SRoque Arcudia Hernandez #define DEFINE_PROP_NGUID_NODEFAULT(_name, _state, _field) \ 185bdc31646SRoque Arcudia Hernandez DEFINE_PROP(_name, _state, _field, qdev_prop_nguid, NvmeNGUID) 186bdc31646SRoque Arcudia Hernandez 18788eea45cSKlaus Jensen typedef struct NvmeNamespaceParams { 18888eea45cSKlaus Jensen bool detached; 18988eea45cSKlaus Jensen bool shared; 19088eea45cSKlaus Jensen uint32_t nsid; 19188eea45cSKlaus Jensen QemuUUID uuid; 192bdc31646SRoque Arcudia Hernandez NvmeNGUID nguid; 1936870cfb8SHeinrich Schuchardt uint64_t eui64; 1943276dde4SHeinrich Schuchardt bool eui64_default; 19588eea45cSKlaus Jensen 19688eea45cSKlaus Jensen uint16_t ms; 19788eea45cSKlaus Jensen uint8_t mset; 19888eea45cSKlaus Jensen uint8_t pi; 19988eea45cSKlaus Jensen uint8_t pil; 20044219b60SNaveen Nagar uint8_t pif; 20188eea45cSKlaus Jensen 20288eea45cSKlaus Jensen uint16_t mssrl; 20388eea45cSKlaus Jensen uint32_t mcl; 20488eea45cSKlaus Jensen uint8_t msrc; 20588eea45cSKlaus Jensen 20688eea45cSKlaus Jensen bool zoned; 20788eea45cSKlaus Jensen bool cross_zone_read; 20888eea45cSKlaus Jensen uint64_t zone_size_bs; 20988eea45cSKlaus Jensen uint64_t zone_cap_bs; 21088eea45cSKlaus Jensen uint32_t max_active_zones; 21188eea45cSKlaus Jensen uint32_t max_open_zones; 21288eea45cSKlaus Jensen uint32_t zd_extension_size; 213e321b4cdSKlaus Jensen 214e321b4cdSKlaus Jensen uint32_t numzrwa; 215e321b4cdSKlaus Jensen uint64_t zrwas; 216e321b4cdSKlaus Jensen uint64_t zrwafg; 21773064edfSJesper Devantier 21873064edfSJesper Devantier struct { 21973064edfSJesper Devantier char *ruhs; 22073064edfSJesper Devantier } fdp; 22188eea45cSKlaus Jensen } NvmeNamespaceParams; 22288eea45cSKlaus Jensen 223ebd1568fSAlan Adamson typedef struct NvmeAtomic { 224ebd1568fSAlan Adamson uint32_t atomic_max_write_size; 225ebd1568fSAlan Adamson bool atomic_writes; 226ebd1568fSAlan Adamson } NvmeAtomic; 227ebd1568fSAlan Adamson 22888eea45cSKlaus Jensen typedef struct NvmeNamespace { 22988eea45cSKlaus Jensen DeviceState parent_obj; 23088eea45cSKlaus Jensen BlockConf blkconf; 23188eea45cSKlaus Jensen int32_t bootindex; 23288eea45cSKlaus Jensen int64_t size; 23388eea45cSKlaus Jensen int64_t moff; 23488eea45cSKlaus Jensen NvmeIdNs id_ns; 23544219b60SNaveen Nagar NvmeIdNsNvm id_ns_nvm; 236*79e49005SArun Kumar NvmeIdNsInd id_ns_ind; 23788eea45cSKlaus Jensen NvmeLBAF lbaf; 238763c05dfSNaveen Nagar unsigned int nlbaf; 23988eea45cSKlaus Jensen size_t lbasz; 24088eea45cSKlaus Jensen const uint32_t *iocs; 24188eea45cSKlaus Jensen uint8_t csi; 24288eea45cSKlaus Jensen uint16_t status; 24388eea45cSKlaus Jensen int attached; 24444219b60SNaveen Nagar uint8_t pif; 24588eea45cSKlaus Jensen 246e321b4cdSKlaus Jensen struct { 247e321b4cdSKlaus Jensen uint16_t zrwas; 248e321b4cdSKlaus Jensen uint16_t zrwafg; 249e321b4cdSKlaus Jensen uint32_t numzrwa; 250e321b4cdSKlaus Jensen } zns; 251e321b4cdSKlaus Jensen 25288eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeNamespace) entry; 25388eea45cSKlaus Jensen 25488eea45cSKlaus Jensen NvmeIdNsZoned *id_ns_zoned; 25588eea45cSKlaus Jensen NvmeZone *zone_array; 25688eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) exp_open_zones; 25788eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) imp_open_zones; 25888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) closed_zones; 25988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) full_zones; 26088eea45cSKlaus Jensen uint32_t num_zones; 26188eea45cSKlaus Jensen uint64_t zone_size; 26288eea45cSKlaus Jensen uint64_t zone_capacity; 26388eea45cSKlaus Jensen uint32_t zone_size_log2; 26488eea45cSKlaus Jensen uint8_t *zd_extensions; 26588eea45cSKlaus Jensen int32_t nr_open_zones; 26688eea45cSKlaus Jensen int32_t nr_active_zones; 26788eea45cSKlaus Jensen 26888eea45cSKlaus Jensen NvmeNamespaceParams params; 269534a93d3SNiklas Cassel NvmeSubsystem *subsys; 27073064edfSJesper Devantier NvmeEnduranceGroup *endgrp; 27188eea45cSKlaus Jensen 27288eea45cSKlaus Jensen struct { 27388eea45cSKlaus Jensen uint32_t err_rec; 27488eea45cSKlaus Jensen } features; 27573064edfSJesper Devantier 27673064edfSJesper Devantier struct { 27773064edfSJesper Devantier uint16_t nphs; 27873064edfSJesper Devantier /* reclaim unit handle identifiers indexed by placement handle */ 27973064edfSJesper Devantier uint16_t *phs; 28073064edfSJesper Devantier } fdp; 28188eea45cSKlaus Jensen } NvmeNamespace; 28288eea45cSKlaus Jensen 28388eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns) 28488eea45cSKlaus Jensen { 28588eea45cSKlaus Jensen if (ns) { 28688eea45cSKlaus Jensen return ns->params.nsid; 28788eea45cSKlaus Jensen } 28888eea45cSKlaus Jensen 28988eea45cSKlaus Jensen return 0; 29088eea45cSKlaus Jensen } 29188eea45cSKlaus Jensen 29288eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) 29388eea45cSKlaus Jensen { 29488eea45cSKlaus Jensen return lba << ns->lbaf.ds; 29588eea45cSKlaus Jensen } 29688eea45cSKlaus Jensen 29788eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba) 29888eea45cSKlaus Jensen { 29988eea45cSKlaus Jensen return ns->lbaf.ms * lba; 30088eea45cSKlaus Jensen } 30188eea45cSKlaus Jensen 30288eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba) 30388eea45cSKlaus Jensen { 30488eea45cSKlaus Jensen return ns->moff + nvme_m2b(ns, lba); 30588eea45cSKlaus Jensen } 30688eea45cSKlaus Jensen 30788eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns) 30888eea45cSKlaus Jensen { 30988eea45cSKlaus Jensen return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas); 31088eea45cSKlaus Jensen } 31188eea45cSKlaus Jensen 31288eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone) 31388eea45cSKlaus Jensen { 31488eea45cSKlaus Jensen return zone->d.zs >> 4; 31588eea45cSKlaus Jensen } 31688eea45cSKlaus Jensen 31788eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state) 31888eea45cSKlaus Jensen { 31988eea45cSKlaus Jensen zone->d.zs = state << 4; 32088eea45cSKlaus Jensen } 32188eea45cSKlaus Jensen 32288eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone) 32388eea45cSKlaus Jensen { 32488eea45cSKlaus Jensen return zone->d.zslba + ns->zone_size; 32588eea45cSKlaus Jensen } 32688eea45cSKlaus Jensen 32788eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone) 32888eea45cSKlaus Jensen { 32988eea45cSKlaus Jensen return zone->d.zslba + zone->d.zcap; 33088eea45cSKlaus Jensen } 33188eea45cSKlaus Jensen 33288eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone) 33388eea45cSKlaus Jensen { 33488eea45cSKlaus Jensen uint8_t st = nvme_get_zone_state(zone); 33588eea45cSKlaus Jensen 33688eea45cSKlaus Jensen return st != NVME_ZONE_STATE_FULL && 33788eea45cSKlaus Jensen st != NVME_ZONE_STATE_READ_ONLY && 33888eea45cSKlaus Jensen st != NVME_ZONE_STATE_OFFLINE; 33988eea45cSKlaus Jensen } 34088eea45cSKlaus Jensen 34188eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns, 34288eea45cSKlaus Jensen uint32_t zone_idx) 34388eea45cSKlaus Jensen { 34488eea45cSKlaus Jensen return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; 34588eea45cSKlaus Jensen } 34688eea45cSKlaus Jensen 34788eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns) 34888eea45cSKlaus Jensen { 34988eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 35088eea45cSKlaus Jensen if (ns->params.max_open_zones) { 35188eea45cSKlaus Jensen ns->nr_open_zones++; 35288eea45cSKlaus Jensen assert(ns->nr_open_zones <= ns->params.max_open_zones); 35388eea45cSKlaus Jensen } 35488eea45cSKlaus Jensen } 35588eea45cSKlaus Jensen 35688eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns) 35788eea45cSKlaus Jensen { 35888eea45cSKlaus Jensen if (ns->params.max_open_zones) { 35988eea45cSKlaus Jensen assert(ns->nr_open_zones > 0); 36088eea45cSKlaus Jensen ns->nr_open_zones--; 36188eea45cSKlaus Jensen } 36288eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0); 36388eea45cSKlaus Jensen } 36488eea45cSKlaus Jensen 36588eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns) 36688eea45cSKlaus Jensen { 36788eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 36888eea45cSKlaus Jensen if (ns->params.max_active_zones) { 36988eea45cSKlaus Jensen ns->nr_active_zones++; 37088eea45cSKlaus Jensen assert(ns->nr_active_zones <= ns->params.max_active_zones); 37188eea45cSKlaus Jensen } 37288eea45cSKlaus Jensen } 37388eea45cSKlaus Jensen 37488eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns) 37588eea45cSKlaus Jensen { 37688eea45cSKlaus Jensen if (ns->params.max_active_zones) { 37788eea45cSKlaus Jensen assert(ns->nr_active_zones > 0); 37888eea45cSKlaus Jensen ns->nr_active_zones--; 37988eea45cSKlaus Jensen assert(ns->nr_active_zones >= ns->nr_open_zones); 38088eea45cSKlaus Jensen } 38188eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0); 38288eea45cSKlaus Jensen } 38388eea45cSKlaus Jensen 38473064edfSJesper Devantier static inline void nvme_fdp_stat_inc(uint64_t *a, uint64_t b) 38573064edfSJesper Devantier { 38673064edfSJesper Devantier uint64_t ret = *a + b; 38773064edfSJesper Devantier *a = ret < *a ? UINT64_MAX : ret; 38873064edfSJesper Devantier } 38973064edfSJesper Devantier 39088eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns); 3915e4f6bccSKlaus Jensen int nvme_ns_setup(NvmeNamespace *ns, Error **errp); 39288eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns); 39388eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns); 39488eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns); 39588eea45cSKlaus Jensen 39688eea45cSKlaus Jensen typedef struct NvmeAsyncEvent { 39788eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeAsyncEvent) entry; 39888eea45cSKlaus Jensen NvmeAerResult result; 39988eea45cSKlaus Jensen } NvmeAsyncEvent; 40088eea45cSKlaus Jensen 40188eea45cSKlaus Jensen enum { 40288eea45cSKlaus Jensen NVME_SG_ALLOC = 1 << 0, 40388eea45cSKlaus Jensen NVME_SG_DMA = 1 << 1, 40488eea45cSKlaus Jensen }; 40588eea45cSKlaus Jensen 40688eea45cSKlaus Jensen typedef struct NvmeSg { 40788eea45cSKlaus Jensen int flags; 40888eea45cSKlaus Jensen 40988eea45cSKlaus Jensen union { 41088eea45cSKlaus Jensen QEMUSGList qsg; 41188eea45cSKlaus Jensen QEMUIOVector iov; 41288eea45cSKlaus Jensen }; 41388eea45cSKlaus Jensen } NvmeSg; 41488eea45cSKlaus Jensen 41588eea45cSKlaus Jensen typedef enum NvmeTxDirection { 41688eea45cSKlaus Jensen NVME_TX_DIRECTION_TO_DEVICE = 0, 41788eea45cSKlaus Jensen NVME_TX_DIRECTION_FROM_DEVICE = 1, 41888eea45cSKlaus Jensen } NvmeTxDirection; 41988eea45cSKlaus Jensen 42088eea45cSKlaus Jensen typedef struct NvmeRequest { 42188eea45cSKlaus Jensen struct NvmeSQueue *sq; 42288eea45cSKlaus Jensen struct NvmeNamespace *ns; 42388eea45cSKlaus Jensen BlockAIOCB *aiocb; 42488eea45cSKlaus Jensen uint16_t status; 42588eea45cSKlaus Jensen void *opaque; 42688eea45cSKlaus Jensen NvmeCqe cqe; 42788eea45cSKlaus Jensen NvmeCmd cmd; 42888eea45cSKlaus Jensen BlockAcctCookie acct; 42988eea45cSKlaus Jensen NvmeSg sg; 430ebd1568fSAlan Adamson bool atomic_write; 43188eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeRequest)entry; 43288eea45cSKlaus Jensen } NvmeRequest; 43388eea45cSKlaus Jensen 43488eea45cSKlaus Jensen typedef struct NvmeBounceContext { 43588eea45cSKlaus Jensen NvmeRequest *req; 43688eea45cSKlaus Jensen 43788eea45cSKlaus Jensen struct { 43888eea45cSKlaus Jensen QEMUIOVector iov; 43988eea45cSKlaus Jensen uint8_t *bounce; 44088eea45cSKlaus Jensen } data, mdata; 44188eea45cSKlaus Jensen } NvmeBounceContext; 44288eea45cSKlaus Jensen 44388eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc) 44488eea45cSKlaus Jensen { 44588eea45cSKlaus Jensen switch (opc) { 44688eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ"; 44788eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ"; 44888eea45cSKlaus Jensen case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE"; 44988eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ"; 45088eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ"; 45188eea45cSKlaus Jensen case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY"; 45288eea45cSKlaus Jensen case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT"; 45388eea45cSKlaus Jensen case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES"; 45488eea45cSKlaus Jensen case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES"; 45588eea45cSKlaus Jensen case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ"; 45688eea45cSKlaus Jensen case NVME_ADM_CMD_NS_ATTACHMENT: return "NVME_ADM_CMD_NS_ATTACHMENT"; 457e181d3daSGollu Appalanaidu case NVME_ADM_CMD_DIRECTIVE_SEND: return "NVME_ADM_CMD_DIRECTIVE_SEND"; 45811871f53SŁukasz Gieryk case NVME_ADM_CMD_VIRT_MNGMT: return "NVME_ADM_CMD_VIRT_MNGMT"; 459e181d3daSGollu Appalanaidu case NVME_ADM_CMD_DIRECTIVE_RECV: return "NVME_ADM_CMD_DIRECTIVE_RECV"; 4603f7fe8deSJinhao Fan case NVME_ADM_CMD_DBBUF_CONFIG: return "NVME_ADM_CMD_DBBUF_CONFIG"; 46188eea45cSKlaus Jensen case NVME_ADM_CMD_FORMAT_NVM: return "NVME_ADM_CMD_FORMAT_NVM"; 46288eea45cSKlaus Jensen default: return "NVME_ADM_CMD_UNKNOWN"; 46388eea45cSKlaus Jensen } 46488eea45cSKlaus Jensen } 46588eea45cSKlaus Jensen 46688eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc) 46788eea45cSKlaus Jensen { 46888eea45cSKlaus Jensen switch (opc) { 46988eea45cSKlaus Jensen case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH"; 47088eea45cSKlaus Jensen case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE"; 47188eea45cSKlaus Jensen case NVME_CMD_READ: return "NVME_NVM_CMD_READ"; 47288eea45cSKlaus Jensen case NVME_CMD_COMPARE: return "NVME_NVM_CMD_COMPARE"; 47388eea45cSKlaus Jensen case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES"; 47488eea45cSKlaus Jensen case NVME_CMD_DSM: return "NVME_NVM_CMD_DSM"; 47588eea45cSKlaus Jensen case NVME_CMD_VERIFY: return "NVME_NVM_CMD_VERIFY"; 47688eea45cSKlaus Jensen case NVME_CMD_COPY: return "NVME_NVM_CMD_COPY"; 47788eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND"; 47888eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV"; 47988eea45cSKlaus Jensen case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND"; 48088eea45cSKlaus Jensen default: return "NVME_NVM_CMD_UNKNOWN"; 48188eea45cSKlaus Jensen } 48288eea45cSKlaus Jensen } 48388eea45cSKlaus Jensen 48488eea45cSKlaus Jensen typedef struct NvmeSQueue { 48588eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 48688eea45cSKlaus Jensen uint16_t sqid; 48788eea45cSKlaus Jensen uint16_t cqid; 48888eea45cSKlaus Jensen uint32_t head; 48988eea45cSKlaus Jensen uint32_t tail; 49088eea45cSKlaus Jensen uint32_t size; 49188eea45cSKlaus Jensen uint64_t dma_addr; 4923f7fe8deSJinhao Fan uint64_t db_addr; 4933f7fe8deSJinhao Fan uint64_t ei_addr; 494d38cc6fdSKlaus Jensen QEMUBH *bh; 4952e53b0b4SJinhao Fan EventNotifier notifier; 4962e53b0b4SJinhao Fan bool ioeventfd_enabled; 49788eea45cSKlaus Jensen NvmeRequest *io_req; 49888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 49988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) out_req_list; 50088eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeSQueue) entry; 50188eea45cSKlaus Jensen } NvmeSQueue; 50288eea45cSKlaus Jensen 50388eea45cSKlaus Jensen typedef struct NvmeCQueue { 50488eea45cSKlaus Jensen struct NvmeCtrl *ctrl; 50588eea45cSKlaus Jensen uint8_t phase; 50688eea45cSKlaus Jensen uint16_t cqid; 50788eea45cSKlaus Jensen uint16_t irq_enabled; 50888eea45cSKlaus Jensen uint32_t head; 50988eea45cSKlaus Jensen uint32_t tail; 51088eea45cSKlaus Jensen uint32_t vector; 51188eea45cSKlaus Jensen uint32_t size; 51288eea45cSKlaus Jensen uint64_t dma_addr; 5133f7fe8deSJinhao Fan uint64_t db_addr; 5143f7fe8deSJinhao Fan uint64_t ei_addr; 515d38cc6fdSKlaus Jensen QEMUBH *bh; 5162e53b0b4SJinhao Fan EventNotifier notifier; 5172e53b0b4SJinhao Fan bool ioeventfd_enabled; 51888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeSQueue) sq_list; 51988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list; 52088eea45cSKlaus Jensen } NvmeCQueue; 52188eea45cSKlaus Jensen 52288eea45cSKlaus Jensen #define TYPE_NVME "nvme" 52388eea45cSKlaus Jensen #define NVME(obj) \ 52488eea45cSKlaus Jensen OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) 52588eea45cSKlaus Jensen 52688eea45cSKlaus Jensen typedef struct NvmeParams { 52788eea45cSKlaus Jensen char *serial; 52888eea45cSKlaus Jensen uint32_t num_queues; /* deprecated since 5.1 */ 52988eea45cSKlaus Jensen uint32_t max_ioqpairs; 53088eea45cSKlaus Jensen uint16_t msix_qsize; 531bc432bc5SJohn Berg uint16_t mqes; 53288eea45cSKlaus Jensen uint32_t cmb_size_mb; 53388eea45cSKlaus Jensen uint8_t aerl; 53488eea45cSKlaus Jensen uint32_t aer_max_queued; 53588eea45cSKlaus Jensen uint8_t mdts; 53688eea45cSKlaus Jensen uint8_t vsl; 53788eea45cSKlaus Jensen bool use_intel_id; 53888eea45cSKlaus Jensen uint8_t zasl; 539cccc2651SNiklas Cassel bool auto_transition_zones; 54088eea45cSKlaus Jensen bool legacy_cmb; 5412e53b0b4SJinhao Fan bool ioeventfd; 542c6159d0eSMinwoo Im uint16_t sriov_max_vfs; 543746d42b1SŁukasz Gieryk uint16_t sriov_vq_flexible; 544746d42b1SŁukasz Gieryk uint16_t sriov_vi_flexible; 54515ef124cSMinwoo Im uint32_t sriov_max_vq_per_vf; 54615ef124cSMinwoo Im uint32_t sriov_max_vi_per_vf; 547fa905f65SKlaus Jensen bool msix_exclusive_bar; 548e4bcb586SKlaus Jensen 549e4bcb586SKlaus Jensen struct { 550e4bcb586SKlaus Jensen bool mem; 551e4bcb586SKlaus Jensen } ctratt; 552ebd1568fSAlan Adamson 553ebd1568fSAlan Adamson uint16_t atomic_awun; 554ebd1568fSAlan Adamson uint16_t atomic_awupf; 555ebd1568fSAlan Adamson bool atomic_dn; 55688eea45cSKlaus Jensen } NvmeParams; 55788eea45cSKlaus Jensen 55888eea45cSKlaus Jensen typedef struct NvmeCtrl { 55988eea45cSKlaus Jensen PCIDevice parent_obj; 56088eea45cSKlaus Jensen MemoryRegion bar0; 56188eea45cSKlaus Jensen MemoryRegion iomem; 56288eea45cSKlaus Jensen NvmeBar bar; 56388eea45cSKlaus Jensen NvmeParams params; 56488eea45cSKlaus Jensen NvmeBus bus; 56588eea45cSKlaus Jensen 56688eea45cSKlaus Jensen uint16_t cntlid; 56788eea45cSKlaus Jensen bool qs_created; 56888eea45cSKlaus Jensen uint32_t page_size; 56988eea45cSKlaus Jensen uint16_t page_bits; 57088eea45cSKlaus Jensen uint16_t max_prp_ents; 57188eea45cSKlaus Jensen uint32_t max_q_ents; 57288eea45cSKlaus Jensen uint8_t outstanding_aers; 57388eea45cSKlaus Jensen uint32_t irq_status; 57483d7ed5cSKlaus Jensen int cq_pending; 57588eea45cSKlaus Jensen uint64_t host_timestamp; /* Timestamp sent by the host */ 57688eea45cSKlaus Jensen uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ 57788eea45cSKlaus Jensen uint64_t starttime_ms; 57888eea45cSKlaus Jensen uint16_t temperature; 57988eea45cSKlaus Jensen uint8_t smart_critical_warning; 580decc0261SŁukasz Gieryk uint32_t conf_msix_qsize; 581decc0261SŁukasz Gieryk uint32_t conf_ioqpairs; 5823f7fe8deSJinhao Fan uint64_t dbbuf_dbs; 5833f7fe8deSJinhao Fan uint64_t dbbuf_eis; 5843f7fe8deSJinhao Fan bool dbbuf_enabled; 58588eea45cSKlaus Jensen 58688eea45cSKlaus Jensen struct { 58788eea45cSKlaus Jensen MemoryRegion mem; 58888eea45cSKlaus Jensen uint8_t *buf; 58988eea45cSKlaus Jensen bool cmse; 59088eea45cSKlaus Jensen hwaddr cba; 59188eea45cSKlaus Jensen } cmb; 59288eea45cSKlaus Jensen 59388eea45cSKlaus Jensen struct { 59488eea45cSKlaus Jensen HostMemoryBackend *dev; 59588eea45cSKlaus Jensen bool cmse; 59688eea45cSKlaus Jensen hwaddr cba; 59788eea45cSKlaus Jensen } pmr; 59888eea45cSKlaus Jensen 59988eea45cSKlaus Jensen uint8_t aer_mask; 60088eea45cSKlaus Jensen NvmeRequest **aer_reqs; 60188eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue; 60288eea45cSKlaus Jensen int aer_queued; 60388eea45cSKlaus Jensen 60488eea45cSKlaus Jensen uint32_t dmrsl; 60588eea45cSKlaus Jensen 60688eea45cSKlaus Jensen /* Namespace ID is started with 1 so bitmap should be 1-based */ 60788eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1) 60888eea45cSKlaus Jensen DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE); 60988eea45cSKlaus Jensen 61088eea45cSKlaus Jensen NvmeSubsystem *subsys; 61188eea45cSKlaus Jensen 61288eea45cSKlaus Jensen NvmeNamespace namespace; 61388eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; 61488eea45cSKlaus Jensen NvmeSQueue **sq; 61588eea45cSKlaus Jensen NvmeCQueue **cq; 61688eea45cSKlaus Jensen NvmeSQueue admin_sq; 61788eea45cSKlaus Jensen NvmeCQueue admin_cq; 61888eea45cSKlaus Jensen NvmeIdCtrl id_ctrl; 61988eea45cSKlaus Jensen 62088eea45cSKlaus Jensen struct { 62188eea45cSKlaus Jensen struct { 62288eea45cSKlaus Jensen uint16_t temp_thresh_hi; 62388eea45cSKlaus Jensen uint16_t temp_thresh_low; 62488eea45cSKlaus Jensen }; 625d0c0697bSNaveen Nagar 62688eea45cSKlaus Jensen uint32_t async_config; 627d0c0697bSNaveen Nagar NvmeHostBehaviorSupport hbs; 62888eea45cSKlaus Jensen } features; 6295e6f963fSLukasz Maniak 6305e6f963fSLukasz Maniak NvmePriCtrlCap pri_ctrl_cap; 6311a494d11SMinwoo Im uint32_t nr_sec_ctrls; 632c6159d0eSMinwoo Im NvmeSecCtrlEntry *sec_ctrl_list; 63311871f53SŁukasz Gieryk struct { 63411871f53SŁukasz Gieryk uint16_t vqrfap; 63511871f53SŁukasz Gieryk uint16_t virfap; 63611871f53SŁukasz Gieryk } next_pri_ctrl_cap; /* These override pri_ctrl_cap after reset */ 637ebd1568fSAlan Adamson uint32_t dn; /* Disable Normal */ 638ebd1568fSAlan Adamson NvmeAtomic atomic; 63988eea45cSKlaus Jensen } NvmeCtrl; 64088eea45cSKlaus Jensen 6411e9c685eSŁukasz Gieryk typedef enum NvmeResetType { 6421e9c685eSŁukasz Gieryk NVME_RESET_FUNCTION = 0, 6431e9c685eSŁukasz Gieryk NVME_RESET_CONTROLLER = 1, 6441e9c685eSŁukasz Gieryk } NvmeResetType; 6451e9c685eSŁukasz Gieryk 64688eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) 64788eea45cSKlaus Jensen { 64888eea45cSKlaus Jensen if (!nsid || nsid > NVME_MAX_NAMESPACES) { 64988eea45cSKlaus Jensen return NULL; 65088eea45cSKlaus Jensen } 65188eea45cSKlaus Jensen 65288eea45cSKlaus Jensen return n->namespaces[nsid]; 65388eea45cSKlaus Jensen } 65488eea45cSKlaus Jensen 65588eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req) 65688eea45cSKlaus Jensen { 65788eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 65888eea45cSKlaus Jensen NvmeCtrl *n = sq->ctrl; 65988eea45cSKlaus Jensen 66088eea45cSKlaus Jensen return n->cq[sq->cqid]; 66188eea45cSKlaus Jensen } 66288eea45cSKlaus Jensen 66388eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req) 66488eea45cSKlaus Jensen { 66588eea45cSKlaus Jensen NvmeSQueue *sq = req->sq; 66688eea45cSKlaus Jensen return sq->ctrl; 66788eea45cSKlaus Jensen } 66888eea45cSKlaus Jensen 66988eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req) 67088eea45cSKlaus Jensen { 67188eea45cSKlaus Jensen if (!req) { 67288eea45cSKlaus Jensen return 0xffff; 67388eea45cSKlaus Jensen } 67488eea45cSKlaus Jensen 67588eea45cSKlaus Jensen return le16_to_cpu(req->cqe.cid); 67688eea45cSKlaus Jensen } 67788eea45cSKlaus Jensen 67899f48ae7SLukasz Maniak static inline NvmeSecCtrlEntry *nvme_sctrl(NvmeCtrl *n) 67999f48ae7SLukasz Maniak { 68099f48ae7SLukasz Maniak PCIDevice *pci_dev = &n->parent_obj; 68199f48ae7SLukasz Maniak NvmeCtrl *pf = NVME(pcie_sriov_get_pf(pci_dev)); 68299f48ae7SLukasz Maniak 68399f48ae7SLukasz Maniak if (pci_is_vf(pci_dev)) { 6841a494d11SMinwoo Im return &pf->sec_ctrl_list[pcie_sriov_vf_number(pci_dev)]; 68599f48ae7SLukasz Maniak } 68699f48ae7SLukasz Maniak 68799f48ae7SLukasz Maniak return NULL; 68899f48ae7SLukasz Maniak } 68999f48ae7SLukasz Maniak 69011871f53SŁukasz Gieryk static inline NvmeSecCtrlEntry *nvme_sctrl_for_cntlid(NvmeCtrl *n, 69111871f53SŁukasz Gieryk uint16_t cntlid) 69211871f53SŁukasz Gieryk { 6931a494d11SMinwoo Im NvmeSecCtrlEntry *list = n->sec_ctrl_list; 69411871f53SŁukasz Gieryk uint8_t i; 69511871f53SŁukasz Gieryk 6961a494d11SMinwoo Im for (i = 0; i < n->nr_sec_ctrls; i++) { 6971a494d11SMinwoo Im if (le16_to_cpu(list[i].scid) == cntlid) { 6981a494d11SMinwoo Im return &list[i]; 69911871f53SŁukasz Gieryk } 70011871f53SŁukasz Gieryk } 70111871f53SŁukasz Gieryk 70211871f53SŁukasz Gieryk return NULL; 70311871f53SŁukasz Gieryk } 70411871f53SŁukasz Gieryk 70588eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); 7068d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len, 70788eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 7088d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_mdata(NvmeCtrl *n, void *ptr, uint32_t len, 70988eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req); 71088eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret); 71188eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, 71288eea45cSKlaus Jensen NvmeCmd *cmd); 71388eea45cSKlaus Jensen 71452581c71SMarkus Armbruster #endif /* HW_NVME_NVME_H */ 715