1#ifndef HW_NVME_H
2#define HW_NVME_H
3
4#include "block/nvme.h"
5#include "nvme-ns.h"
6
7#define NVME_MAX_NAMESPACES 256
8
9typedef struct NvmeParams {
10 char *serial;
11 uint32_t num_queues;
12 uint32_t max_ioqpairs;
13 uint16_t msix_qsize;
14 uint32_t cmb_size_mb;
15 uint8_t aerl;
16 uint32_t aer_max_queued;
17 uint8_t mdts;
18 bool use_intel_id;
19} NvmeParams;
20
21typedef struct NvmeAsyncEvent {
22 QTAILQ_ENTRY(NvmeAsyncEvent) entry;
23 NvmeAerResult result;
24} NvmeAsyncEvent;
25
26typedef struct NvmeRequest {
27 struct NvmeSQueue *sq;
28 struct NvmeNamespace *ns;
29 BlockAIOCB *aiocb;
30 uint16_t status;
31 NvmeCqe cqe;
32 NvmeCmd cmd;
33 BlockAcctCookie acct;
34 QEMUSGList qsg;
35 QEMUIOVector iov;
36 QTAILQ_ENTRY(NvmeRequest)entry;
37} NvmeRequest;
38
39static inline const char *nvme_adm_opc_str(uint8_t opc)
40{
41 switch (opc) {
42 case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ";
43 case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ";
44 case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE";
45 case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ";
46 case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ";
47 case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY";
48 case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT";
49 case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES";
50 case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES";
51 case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ";
52 default: return "NVME_ADM_CMD_UNKNOWN";
53 }
54}
55
56static inline const char *nvme_io_opc_str(uint8_t opc)
57{
58 switch (opc) {
59 case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH";
60 case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE";
61 case NVME_CMD_READ: return "NVME_NVM_CMD_READ";
62 case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES";
63 default: return "NVME_NVM_CMD_UNKNOWN";
64 }
65}
66
67typedef struct NvmeSQueue {
68 struct NvmeCtrl *ctrl;
69 uint16_t sqid;
70 uint16_t cqid;
71 uint32_t head;
72 uint32_t tail;
73 uint32_t size;
74 uint64_t dma_addr;
75 QEMUTimer *timer;
76 NvmeRequest *io_req;
77 QTAILQ_HEAD(, NvmeRequest) req_list;
78 QTAILQ_HEAD(, NvmeRequest) out_req_list;
79 QTAILQ_ENTRY(NvmeSQueue) entry;
80} NvmeSQueue;
81
82typedef struct NvmeCQueue {
83 struct NvmeCtrl *ctrl;
84 uint8_t phase;
85 uint16_t cqid;
86 uint16_t irq_enabled;
87 uint32_t head;
88 uint32_t tail;
89 uint32_t vector;
90 uint32_t size;
91 uint64_t dma_addr;
92 QEMUTimer *timer;
93 QTAILQ_HEAD(, NvmeSQueue) sq_list;
94 QTAILQ_HEAD(, NvmeRequest) req_list;
95} NvmeCQueue;
96
97#define TYPE_NVME_BUS "nvme-bus"
98#define NVME_BUS(obj) OBJECT_CHECK(NvmeBus, (obj), TYPE_NVME_BUS)
99
100typedef struct NvmeBus {
101 BusState parent_bus;
102} NvmeBus;
103
104#define TYPE_NVME "nvme"
105#define NVME(obj) \
106 OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
107
108typedef struct NvmeFeatureVal {
109 struct {
110 uint16_t temp_thresh_hi;
111 uint16_t temp_thresh_low;
112 };
113 uint32_t async_config;
114 uint32_t vwc;
115} NvmeFeatureVal;
116
117typedef struct NvmeCtrl {
118 PCIDevice parent_obj;
119 MemoryRegion iomem;
120 MemoryRegion ctrl_mem;
121 NvmeBar bar;
122 NvmeParams params;
123 NvmeBus bus;
124 BlockConf conf;
125
126 bool qs_created;
127 uint32_t page_size;
128 uint16_t page_bits;
129 uint16_t max_prp_ents;
130 uint16_t cqe_size;
131 uint16_t sqe_size;
132 uint32_t reg_size;
133 uint32_t num_namespaces;
134 uint32_t max_q_ents;
135 uint8_t outstanding_aers;
136 uint8_t *cmbuf;
137 uint32_t irq_status;
138 uint64_t host_timestamp;
139 uint64_t timestamp_set_qemu_clock_ms;
140 uint64_t starttime_ms;
141 uint16_t temperature;
142
143 HostMemoryBackend *pmrdev;
144
145 uint8_t aer_mask;
146 NvmeRequest **aer_reqs;
147 QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
148 int aer_queued;
149
150 NvmeNamespace namespace;
151 NvmeNamespace *namespaces[NVME_MAX_NAMESPACES];
152 NvmeSQueue **sq;
153 NvmeCQueue **cq;
154 NvmeSQueue admin_sq;
155 NvmeCQueue admin_cq;
156 NvmeIdCtrl id_ctrl;
157 NvmeFeatureVal features;
158} NvmeCtrl;
159
160static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
161{
162 if (!nsid || nsid > n->num_namespaces) {
163 return NULL;
164 }
165
166 return n->namespaces[nsid - 1];
167}
168
169static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
170{
171 NvmeSQueue *sq = req->sq;
172 NvmeCtrl *n = sq->ctrl;
173
174 return n->cq[sq->cqid];
175}
176
177static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req)
178{
179 NvmeSQueue *sq = req->sq;
180 return sq->ctrl;
181}
182
183int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp);
184
185#endif
186