xref: /openbmc/qemu/hw/nvme/nvme.h (revision 763c05dfb08c5fff86275788de7f11e899167167)
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;
117e321b4cdSKlaus Jensen 
118e321b4cdSKlaus Jensen     uint32_t numzrwa;
119e321b4cdSKlaus Jensen     uint64_t zrwas;
120e321b4cdSKlaus 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;
131*763c05dfSNaveen Nagar     unsigned int nlbaf;
13288eea45cSKlaus Jensen     size_t       lbasz;
13388eea45cSKlaus Jensen     const uint32_t *iocs;
13488eea45cSKlaus Jensen     uint8_t      csi;
13588eea45cSKlaus Jensen     uint16_t     status;
13688eea45cSKlaus Jensen     int          attached;
13788eea45cSKlaus Jensen 
138e321b4cdSKlaus Jensen     struct {
139e321b4cdSKlaus Jensen         uint16_t zrwas;
140e321b4cdSKlaus Jensen         uint16_t zrwafg;
141e321b4cdSKlaus Jensen         uint32_t numzrwa;
142e321b4cdSKlaus Jensen     } zns;
143e321b4cdSKlaus Jensen 
14488eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeNamespace) entry;
14588eea45cSKlaus Jensen 
14688eea45cSKlaus Jensen     NvmeIdNsZoned   *id_ns_zoned;
14788eea45cSKlaus Jensen     NvmeZone        *zone_array;
14888eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) exp_open_zones;
14988eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) imp_open_zones;
15088eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) closed_zones;
15188eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) full_zones;
15288eea45cSKlaus Jensen     uint32_t        num_zones;
15388eea45cSKlaus Jensen     uint64_t        zone_size;
15488eea45cSKlaus Jensen     uint64_t        zone_capacity;
15588eea45cSKlaus Jensen     uint32_t        zone_size_log2;
15688eea45cSKlaus Jensen     uint8_t         *zd_extensions;
15788eea45cSKlaus Jensen     int32_t         nr_open_zones;
15888eea45cSKlaus Jensen     int32_t         nr_active_zones;
15988eea45cSKlaus Jensen 
16088eea45cSKlaus Jensen     NvmeNamespaceParams params;
16188eea45cSKlaus Jensen 
16288eea45cSKlaus Jensen     struct {
16388eea45cSKlaus Jensen         uint32_t err_rec;
16488eea45cSKlaus Jensen     } features;
16588eea45cSKlaus Jensen } NvmeNamespace;
16688eea45cSKlaus Jensen 
16788eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns)
16888eea45cSKlaus Jensen {
16988eea45cSKlaus Jensen     if (ns) {
17088eea45cSKlaus Jensen         return ns->params.nsid;
17188eea45cSKlaus Jensen     }
17288eea45cSKlaus Jensen 
17388eea45cSKlaus Jensen     return 0;
17488eea45cSKlaus Jensen }
17588eea45cSKlaus Jensen 
17688eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
17788eea45cSKlaus Jensen {
17888eea45cSKlaus Jensen     return lba << ns->lbaf.ds;
17988eea45cSKlaus Jensen }
18088eea45cSKlaus Jensen 
18188eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba)
18288eea45cSKlaus Jensen {
18388eea45cSKlaus Jensen     return ns->lbaf.ms * lba;
18488eea45cSKlaus Jensen }
18588eea45cSKlaus Jensen 
18688eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba)
18788eea45cSKlaus Jensen {
18888eea45cSKlaus Jensen     return ns->moff + nvme_m2b(ns, lba);
18988eea45cSKlaus Jensen }
19088eea45cSKlaus Jensen 
19188eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns)
19288eea45cSKlaus Jensen {
19388eea45cSKlaus Jensen     return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas);
19488eea45cSKlaus Jensen }
19588eea45cSKlaus Jensen 
19688eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone)
19788eea45cSKlaus Jensen {
19888eea45cSKlaus Jensen     return zone->d.zs >> 4;
19988eea45cSKlaus Jensen }
20088eea45cSKlaus Jensen 
20188eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state)
20288eea45cSKlaus Jensen {
20388eea45cSKlaus Jensen     zone->d.zs = state << 4;
20488eea45cSKlaus Jensen }
20588eea45cSKlaus Jensen 
20688eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone)
20788eea45cSKlaus Jensen {
20888eea45cSKlaus Jensen     return zone->d.zslba + ns->zone_size;
20988eea45cSKlaus Jensen }
21088eea45cSKlaus Jensen 
21188eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone)
21288eea45cSKlaus Jensen {
21388eea45cSKlaus Jensen     return zone->d.zslba + zone->d.zcap;
21488eea45cSKlaus Jensen }
21588eea45cSKlaus Jensen 
21688eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone)
21788eea45cSKlaus Jensen {
21888eea45cSKlaus Jensen     uint8_t st = nvme_get_zone_state(zone);
21988eea45cSKlaus Jensen 
22088eea45cSKlaus Jensen     return st != NVME_ZONE_STATE_FULL &&
22188eea45cSKlaus Jensen            st != NVME_ZONE_STATE_READ_ONLY &&
22288eea45cSKlaus Jensen            st != NVME_ZONE_STATE_OFFLINE;
22388eea45cSKlaus Jensen }
22488eea45cSKlaus Jensen 
22588eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns,
22688eea45cSKlaus Jensen                                              uint32_t zone_idx)
22788eea45cSKlaus Jensen {
22888eea45cSKlaus Jensen     return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size];
22988eea45cSKlaus Jensen }
23088eea45cSKlaus Jensen 
23188eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns)
23288eea45cSKlaus Jensen {
23388eea45cSKlaus Jensen     assert(ns->nr_open_zones >= 0);
23488eea45cSKlaus Jensen     if (ns->params.max_open_zones) {
23588eea45cSKlaus Jensen         ns->nr_open_zones++;
23688eea45cSKlaus Jensen         assert(ns->nr_open_zones <= ns->params.max_open_zones);
23788eea45cSKlaus Jensen     }
23888eea45cSKlaus Jensen }
23988eea45cSKlaus Jensen 
24088eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns)
24188eea45cSKlaus Jensen {
24288eea45cSKlaus Jensen     if (ns->params.max_open_zones) {
24388eea45cSKlaus Jensen         assert(ns->nr_open_zones > 0);
24488eea45cSKlaus Jensen         ns->nr_open_zones--;
24588eea45cSKlaus Jensen     }
24688eea45cSKlaus Jensen     assert(ns->nr_open_zones >= 0);
24788eea45cSKlaus Jensen }
24888eea45cSKlaus Jensen 
24988eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns)
25088eea45cSKlaus Jensen {
25188eea45cSKlaus Jensen     assert(ns->nr_active_zones >= 0);
25288eea45cSKlaus Jensen     if (ns->params.max_active_zones) {
25388eea45cSKlaus Jensen         ns->nr_active_zones++;
25488eea45cSKlaus Jensen         assert(ns->nr_active_zones <= ns->params.max_active_zones);
25588eea45cSKlaus Jensen     }
25688eea45cSKlaus Jensen }
25788eea45cSKlaus Jensen 
25888eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns)
25988eea45cSKlaus Jensen {
26088eea45cSKlaus Jensen     if (ns->params.max_active_zones) {
26188eea45cSKlaus Jensen         assert(ns->nr_active_zones > 0);
26288eea45cSKlaus Jensen         ns->nr_active_zones--;
26388eea45cSKlaus Jensen         assert(ns->nr_active_zones >= ns->nr_open_zones);
26488eea45cSKlaus Jensen     }
26588eea45cSKlaus Jensen     assert(ns->nr_active_zones >= 0);
26688eea45cSKlaus Jensen }
26788eea45cSKlaus Jensen 
26888eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns);
2695e4f6bccSKlaus Jensen int nvme_ns_setup(NvmeNamespace *ns, Error **errp);
27088eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns);
27188eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns);
27288eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns);
27388eea45cSKlaus Jensen 
27488eea45cSKlaus Jensen typedef struct NvmeAsyncEvent {
27588eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeAsyncEvent) entry;
27688eea45cSKlaus Jensen     NvmeAerResult result;
27788eea45cSKlaus Jensen } NvmeAsyncEvent;
27888eea45cSKlaus Jensen 
27988eea45cSKlaus Jensen enum {
28088eea45cSKlaus Jensen     NVME_SG_ALLOC = 1 << 0,
28188eea45cSKlaus Jensen     NVME_SG_DMA   = 1 << 1,
28288eea45cSKlaus Jensen };
28388eea45cSKlaus Jensen 
28488eea45cSKlaus Jensen typedef struct NvmeSg {
28588eea45cSKlaus Jensen     int flags;
28688eea45cSKlaus Jensen 
28788eea45cSKlaus Jensen     union {
28888eea45cSKlaus Jensen         QEMUSGList   qsg;
28988eea45cSKlaus Jensen         QEMUIOVector iov;
29088eea45cSKlaus Jensen     };
29188eea45cSKlaus Jensen } NvmeSg;
29288eea45cSKlaus Jensen 
29388eea45cSKlaus Jensen typedef enum NvmeTxDirection {
29488eea45cSKlaus Jensen     NVME_TX_DIRECTION_TO_DEVICE   = 0,
29588eea45cSKlaus Jensen     NVME_TX_DIRECTION_FROM_DEVICE = 1,
29688eea45cSKlaus Jensen } NvmeTxDirection;
29788eea45cSKlaus Jensen 
29888eea45cSKlaus Jensen typedef struct NvmeRequest {
29988eea45cSKlaus Jensen     struct NvmeSQueue       *sq;
30088eea45cSKlaus Jensen     struct NvmeNamespace    *ns;
30188eea45cSKlaus Jensen     BlockAIOCB              *aiocb;
30288eea45cSKlaus Jensen     uint16_t                status;
30388eea45cSKlaus Jensen     void                    *opaque;
30488eea45cSKlaus Jensen     NvmeCqe                 cqe;
30588eea45cSKlaus Jensen     NvmeCmd                 cmd;
30688eea45cSKlaus Jensen     BlockAcctCookie         acct;
30788eea45cSKlaus Jensen     NvmeSg                  sg;
30888eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeRequest)entry;
30988eea45cSKlaus Jensen } NvmeRequest;
31088eea45cSKlaus Jensen 
31188eea45cSKlaus Jensen typedef struct NvmeBounceContext {
31288eea45cSKlaus Jensen     NvmeRequest *req;
31388eea45cSKlaus Jensen 
31488eea45cSKlaus Jensen     struct {
31588eea45cSKlaus Jensen         QEMUIOVector iov;
31688eea45cSKlaus Jensen         uint8_t *bounce;
31788eea45cSKlaus Jensen     } data, mdata;
31888eea45cSKlaus Jensen } NvmeBounceContext;
31988eea45cSKlaus Jensen 
32088eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc)
32188eea45cSKlaus Jensen {
32288eea45cSKlaus Jensen     switch (opc) {
32388eea45cSKlaus Jensen     case NVME_ADM_CMD_DELETE_SQ:        return "NVME_ADM_CMD_DELETE_SQ";
32488eea45cSKlaus Jensen     case NVME_ADM_CMD_CREATE_SQ:        return "NVME_ADM_CMD_CREATE_SQ";
32588eea45cSKlaus Jensen     case NVME_ADM_CMD_GET_LOG_PAGE:     return "NVME_ADM_CMD_GET_LOG_PAGE";
32688eea45cSKlaus Jensen     case NVME_ADM_CMD_DELETE_CQ:        return "NVME_ADM_CMD_DELETE_CQ";
32788eea45cSKlaus Jensen     case NVME_ADM_CMD_CREATE_CQ:        return "NVME_ADM_CMD_CREATE_CQ";
32888eea45cSKlaus Jensen     case NVME_ADM_CMD_IDENTIFY:         return "NVME_ADM_CMD_IDENTIFY";
32988eea45cSKlaus Jensen     case NVME_ADM_CMD_ABORT:            return "NVME_ADM_CMD_ABORT";
33088eea45cSKlaus Jensen     case NVME_ADM_CMD_SET_FEATURES:     return "NVME_ADM_CMD_SET_FEATURES";
33188eea45cSKlaus Jensen     case NVME_ADM_CMD_GET_FEATURES:     return "NVME_ADM_CMD_GET_FEATURES";
33288eea45cSKlaus Jensen     case NVME_ADM_CMD_ASYNC_EV_REQ:     return "NVME_ADM_CMD_ASYNC_EV_REQ";
33388eea45cSKlaus Jensen     case NVME_ADM_CMD_NS_ATTACHMENT:    return "NVME_ADM_CMD_NS_ATTACHMENT";
33488eea45cSKlaus Jensen     case NVME_ADM_CMD_FORMAT_NVM:       return "NVME_ADM_CMD_FORMAT_NVM";
33588eea45cSKlaus Jensen     default:                            return "NVME_ADM_CMD_UNKNOWN";
33688eea45cSKlaus Jensen     }
33788eea45cSKlaus Jensen }
33888eea45cSKlaus Jensen 
33988eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc)
34088eea45cSKlaus Jensen {
34188eea45cSKlaus Jensen     switch (opc) {
34288eea45cSKlaus Jensen     case NVME_CMD_FLUSH:            return "NVME_NVM_CMD_FLUSH";
34388eea45cSKlaus Jensen     case NVME_CMD_WRITE:            return "NVME_NVM_CMD_WRITE";
34488eea45cSKlaus Jensen     case NVME_CMD_READ:             return "NVME_NVM_CMD_READ";
34588eea45cSKlaus Jensen     case NVME_CMD_COMPARE:          return "NVME_NVM_CMD_COMPARE";
34688eea45cSKlaus Jensen     case NVME_CMD_WRITE_ZEROES:     return "NVME_NVM_CMD_WRITE_ZEROES";
34788eea45cSKlaus Jensen     case NVME_CMD_DSM:              return "NVME_NVM_CMD_DSM";
34888eea45cSKlaus Jensen     case NVME_CMD_VERIFY:           return "NVME_NVM_CMD_VERIFY";
34988eea45cSKlaus Jensen     case NVME_CMD_COPY:             return "NVME_NVM_CMD_COPY";
35088eea45cSKlaus Jensen     case NVME_CMD_ZONE_MGMT_SEND:   return "NVME_ZONED_CMD_MGMT_SEND";
35188eea45cSKlaus Jensen     case NVME_CMD_ZONE_MGMT_RECV:   return "NVME_ZONED_CMD_MGMT_RECV";
35288eea45cSKlaus Jensen     case NVME_CMD_ZONE_APPEND:      return "NVME_ZONED_CMD_ZONE_APPEND";
35388eea45cSKlaus Jensen     default:                        return "NVME_NVM_CMD_UNKNOWN";
35488eea45cSKlaus Jensen     }
35588eea45cSKlaus Jensen }
35688eea45cSKlaus Jensen 
35788eea45cSKlaus Jensen typedef struct NvmeSQueue {
35888eea45cSKlaus Jensen     struct NvmeCtrl *ctrl;
35988eea45cSKlaus Jensen     uint16_t    sqid;
36088eea45cSKlaus Jensen     uint16_t    cqid;
36188eea45cSKlaus Jensen     uint32_t    head;
36288eea45cSKlaus Jensen     uint32_t    tail;
36388eea45cSKlaus Jensen     uint32_t    size;
36488eea45cSKlaus Jensen     uint64_t    dma_addr;
36588eea45cSKlaus Jensen     QEMUTimer   *timer;
36688eea45cSKlaus Jensen     NvmeRequest *io_req;
36788eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeRequest) req_list;
36888eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeRequest) out_req_list;
36988eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeSQueue) entry;
37088eea45cSKlaus Jensen } NvmeSQueue;
37188eea45cSKlaus Jensen 
37288eea45cSKlaus Jensen typedef struct NvmeCQueue {
37388eea45cSKlaus Jensen     struct NvmeCtrl *ctrl;
37488eea45cSKlaus Jensen     uint8_t     phase;
37588eea45cSKlaus Jensen     uint16_t    cqid;
37688eea45cSKlaus Jensen     uint16_t    irq_enabled;
37788eea45cSKlaus Jensen     uint32_t    head;
37888eea45cSKlaus Jensen     uint32_t    tail;
37988eea45cSKlaus Jensen     uint32_t    vector;
38088eea45cSKlaus Jensen     uint32_t    size;
38188eea45cSKlaus Jensen     uint64_t    dma_addr;
38288eea45cSKlaus Jensen     QEMUTimer   *timer;
38388eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeSQueue) sq_list;
38488eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeRequest) req_list;
38588eea45cSKlaus Jensen } NvmeCQueue;
38688eea45cSKlaus Jensen 
38788eea45cSKlaus Jensen #define TYPE_NVME "nvme"
38888eea45cSKlaus Jensen #define NVME(obj) \
38988eea45cSKlaus Jensen         OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
39088eea45cSKlaus Jensen 
39188eea45cSKlaus Jensen typedef struct NvmeParams {
39288eea45cSKlaus Jensen     char     *serial;
39388eea45cSKlaus Jensen     uint32_t num_queues; /* deprecated since 5.1 */
39488eea45cSKlaus Jensen     uint32_t max_ioqpairs;
39588eea45cSKlaus Jensen     uint16_t msix_qsize;
39688eea45cSKlaus Jensen     uint32_t cmb_size_mb;
39788eea45cSKlaus Jensen     uint8_t  aerl;
39888eea45cSKlaus Jensen     uint32_t aer_max_queued;
39988eea45cSKlaus Jensen     uint8_t  mdts;
40088eea45cSKlaus Jensen     uint8_t  vsl;
40188eea45cSKlaus Jensen     bool     use_intel_id;
40288eea45cSKlaus Jensen     uint8_t  zasl;
403cccc2651SNiklas Cassel     bool     auto_transition_zones;
40488eea45cSKlaus Jensen     bool     legacy_cmb;
40588eea45cSKlaus Jensen } NvmeParams;
40688eea45cSKlaus Jensen 
40788eea45cSKlaus Jensen typedef struct NvmeCtrl {
40888eea45cSKlaus Jensen     PCIDevice    parent_obj;
40988eea45cSKlaus Jensen     MemoryRegion bar0;
41088eea45cSKlaus Jensen     MemoryRegion iomem;
41188eea45cSKlaus Jensen     NvmeBar      bar;
41288eea45cSKlaus Jensen     NvmeParams   params;
41388eea45cSKlaus Jensen     NvmeBus      bus;
41488eea45cSKlaus Jensen 
41588eea45cSKlaus Jensen     uint16_t    cntlid;
41688eea45cSKlaus Jensen     bool        qs_created;
41788eea45cSKlaus Jensen     uint32_t    page_size;
41888eea45cSKlaus Jensen     uint16_t    page_bits;
41988eea45cSKlaus Jensen     uint16_t    max_prp_ents;
42088eea45cSKlaus Jensen     uint16_t    cqe_size;
42188eea45cSKlaus Jensen     uint16_t    sqe_size;
42288eea45cSKlaus Jensen     uint32_t    reg_size;
42388eea45cSKlaus Jensen     uint32_t    max_q_ents;
42488eea45cSKlaus Jensen     uint8_t     outstanding_aers;
42588eea45cSKlaus Jensen     uint32_t    irq_status;
42683d7ed5cSKlaus Jensen     int         cq_pending;
42788eea45cSKlaus Jensen     uint64_t    host_timestamp;                 /* Timestamp sent by the host */
42888eea45cSKlaus Jensen     uint64_t    timestamp_set_qemu_clock_ms;    /* QEMU clock time */
42988eea45cSKlaus Jensen     uint64_t    starttime_ms;
43088eea45cSKlaus Jensen     uint16_t    temperature;
43188eea45cSKlaus Jensen     uint8_t     smart_critical_warning;
43288eea45cSKlaus Jensen 
43388eea45cSKlaus Jensen     struct {
43488eea45cSKlaus Jensen         MemoryRegion mem;
43588eea45cSKlaus Jensen         uint8_t      *buf;
43688eea45cSKlaus Jensen         bool         cmse;
43788eea45cSKlaus Jensen         hwaddr       cba;
43888eea45cSKlaus Jensen     } cmb;
43988eea45cSKlaus Jensen 
44088eea45cSKlaus Jensen     struct {
44188eea45cSKlaus Jensen         HostMemoryBackend *dev;
44288eea45cSKlaus Jensen         bool              cmse;
44388eea45cSKlaus Jensen         hwaddr            cba;
44488eea45cSKlaus Jensen     } pmr;
44588eea45cSKlaus Jensen 
44688eea45cSKlaus Jensen     uint8_t     aer_mask;
44788eea45cSKlaus Jensen     NvmeRequest **aer_reqs;
44888eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
44988eea45cSKlaus Jensen     int         aer_queued;
45088eea45cSKlaus Jensen 
45188eea45cSKlaus Jensen     uint32_t    dmrsl;
45288eea45cSKlaus Jensen 
45388eea45cSKlaus Jensen     /* Namespace ID is started with 1 so bitmap should be 1-based */
45488eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE  (NVME_MAX_NAMESPACES + 1)
45588eea45cSKlaus Jensen     DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE);
45688eea45cSKlaus Jensen 
45788eea45cSKlaus Jensen     NvmeSubsystem   *subsys;
45888eea45cSKlaus Jensen 
45988eea45cSKlaus Jensen     NvmeNamespace   namespace;
46088eea45cSKlaus Jensen     NvmeNamespace   *namespaces[NVME_MAX_NAMESPACES + 1];
46188eea45cSKlaus Jensen     NvmeSQueue      **sq;
46288eea45cSKlaus Jensen     NvmeCQueue      **cq;
46388eea45cSKlaus Jensen     NvmeSQueue      admin_sq;
46488eea45cSKlaus Jensen     NvmeCQueue      admin_cq;
46588eea45cSKlaus Jensen     NvmeIdCtrl      id_ctrl;
46688eea45cSKlaus Jensen 
46788eea45cSKlaus Jensen     struct {
46888eea45cSKlaus Jensen         struct {
46988eea45cSKlaus Jensen             uint16_t temp_thresh_hi;
47088eea45cSKlaus Jensen             uint16_t temp_thresh_low;
47188eea45cSKlaus Jensen         };
472d0c0697bSNaveen Nagar 
47388eea45cSKlaus Jensen         uint32_t                async_config;
474d0c0697bSNaveen Nagar         NvmeHostBehaviorSupport hbs;
47588eea45cSKlaus Jensen     } features;
47688eea45cSKlaus Jensen } NvmeCtrl;
47788eea45cSKlaus Jensen 
47888eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
47988eea45cSKlaus Jensen {
48088eea45cSKlaus Jensen     if (!nsid || nsid > NVME_MAX_NAMESPACES) {
48188eea45cSKlaus Jensen         return NULL;
48288eea45cSKlaus Jensen     }
48388eea45cSKlaus Jensen 
48488eea45cSKlaus Jensen     return n->namespaces[nsid];
48588eea45cSKlaus Jensen }
48688eea45cSKlaus Jensen 
48788eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
48888eea45cSKlaus Jensen {
48988eea45cSKlaus Jensen     NvmeSQueue *sq = req->sq;
49088eea45cSKlaus Jensen     NvmeCtrl *n = sq->ctrl;
49188eea45cSKlaus Jensen 
49288eea45cSKlaus Jensen     return n->cq[sq->cqid];
49388eea45cSKlaus Jensen }
49488eea45cSKlaus Jensen 
49588eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req)
49688eea45cSKlaus Jensen {
49788eea45cSKlaus Jensen     NvmeSQueue *sq = req->sq;
49888eea45cSKlaus Jensen     return sq->ctrl;
49988eea45cSKlaus Jensen }
50088eea45cSKlaus Jensen 
50188eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req)
50288eea45cSKlaus Jensen {
50388eea45cSKlaus Jensen     if (!req) {
50488eea45cSKlaus Jensen         return 0xffff;
50588eea45cSKlaus Jensen     }
50688eea45cSKlaus Jensen 
50788eea45cSKlaus Jensen     return le16_to_cpu(req->cqe.cid);
50888eea45cSKlaus Jensen }
50988eea45cSKlaus Jensen 
51088eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns);
5118d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len,
51288eea45cSKlaus Jensen                           NvmeTxDirection dir, NvmeRequest *req);
5138d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_mdata(NvmeCtrl *n, void *ptr, uint32_t len,
51488eea45cSKlaus Jensen                            NvmeTxDirection dir, NvmeRequest *req);
51588eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret);
51688eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len,
51788eea45cSKlaus Jensen                        NvmeCmd *cmd);
51888eea45cSKlaus Jensen 
51988eea45cSKlaus Jensen #endif /* HW_NVME_INTERNAL_H */
520