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