xref: /illumos-gate/usr/src/uts/common/io/nvme/nvme_reg.h (revision 533affcb)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020 Joyent, Inc.
14  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
15  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
16  * Copyright 2024 Oxide Computer Company
17  */
18 
19 /*
20  * NVMe hardware interface
21  */
22 
23 #ifndef _NVME_REG_H
24 #define	_NVME_REG_H
25 
26 #include <sys/nvme.h>
27 
28 #pragma pack(1)
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 
35 /*
36  * NVMe constants
37  */
38 #define	NVME_MAX_ADMIN_QUEUE_LEN	4096
39 
40 /*
41  * NVMe registers and register fields
42  */
43 #define	NVME_REG_CAP	0x0		/* Controller Capabilities */
44 #define	NVME_REG_VS	0x8		/* Version */
45 #define	NVME_REG_INTMS	0xc		/* Interrupt Mask Set */
46 #define	NVME_REG_INTMC	0x10		/* Interrupt Mask Clear */
47 #define	NVME_REG_CC	0x14		/* Controller Configuration */
48 #define	NVME_REG_CSTS	0x1c		/* Controller Status */
49 #define	NVME_REG_NSSR	0x20		/* NVM Subsystem Reset */
50 #define	NVME_REG_AQA	0x24		/* Admin Queue Attributes */
51 #define	NVME_REG_ASQ	0x28		/* Admin Submission Queue */
52 #define	NVME_REG_ACQ	0x30		/* Admin Completion Qeueu */
53 #define	NVME_REG_CMBLOC	0x38		/* Controller Memory Buffer Location */
54 #define	NVME_REG_CMBSZ	0x3C		/* Controller Memory Buffer Size */
55 #define	NVME_REG_BPINFO	0x40		/* Boot Partition Information */
56 #define	NVME_REG_BPRSEL	0x44		/* Boot Partition Read Select */
57 #define	NVME_REG_BPMBL	0x48		/* Boot Partition Memory Buffer Loc */
58 #define	NVME_REG_SQTDBL(nvme, n) \
59 	(0x1000 + ((2 * (n)) * nvme->n_doorbell_stride))
60 #define	NVME_REG_CQHDBL(nvme, n) \
61 	(0x1000 + ((2 * (n) + 1) * nvme->n_doorbell_stride))
62 
63 #define	 NVME_CAP_CSS_NVM	1	/* NVM Command Set */
64 #define	 NVME_CAP_AMS_WRR	1	/* Weighted Round-Robin */
65 
66 /* CAP -- Controller Capabilities */
67 typedef union {
68 	struct {
69 		uint16_t cap_mqes;	/* Maximum Queue Entries Supported */
70 		uint8_t cap_cqr:1;	/* Contiguous Queues Required */
71 		uint8_t cap_ams:2;	/* Arbitration Mechanisms Supported */
72 		uint8_t cap_rsvd1:5;
73 		uint8_t cap_to;		/* Timeout */
74 		uint16_t cap_dstrd:4;	/* Doorbell Stride */
75 		uint16_t cap_nssrs:1;	/* NVM Subsystem Reset Supported */
76 		uint16_t cap_css:8;	/* Command Sets Supported */
77 		uint16_t cap_rsvd2:2;
78 		uint8_t cap_bps:1;	/* Boot Partition Support */
79 		uint8_t cap_mpsmin:4;	/* Memory Page Size Minimum */
80 		uint8_t cap_mpsmax:4;	/* Memory Page Size Maximum */
81 		uint8_t cap_rsvd3;
82 	} b;
83 	uint64_t r;
84 } nvme_reg_cap_t;
85 
86 /* VS -- Version */
87 typedef union {
88 	struct {
89 		uint8_t vs_rsvd;
90 		uint8_t vs_mnr;		/* Minor Version Number */
91 		uint16_t vs_mjr;	/* Major Version Number */
92 	} b;
93 	uint32_t r;
94 } nvme_reg_vs_t;
95 
96 /* CC -- Controller Configuration */
97 #define	NVME_CC_SHN_NORMAL	1	/* Normal Shutdown Notification */
98 #define	NVME_CC_SHN_ABRUPT	2	/* Abrupt Shutdown Notification */
99 
100 typedef union {
101 	struct {
102 		uint16_t cc_en:1;	/* Enable */
103 		uint16_t cc_rsvd1:3;
104 		uint16_t cc_css:3;	/* I/O Command Set Selected */
105 		uint16_t cc_mps:4;	/* Memory Page Size */
106 		uint16_t cc_ams:3;	/* Arbitration Mechanism Selected */
107 		uint16_t cc_shn:2;	/* Shutdown Notification */
108 		uint8_t cc_iosqes:4;	/* I/O Submission Queue Entry Size */
109 		uint8_t cc_iocqes:4;	/* I/O Completion Queue Entry Size */
110 		uint8_t cc_rsvd2;
111 	} b;
112 	uint32_t r;
113 } nvme_reg_cc_t;
114 
115 /* CSTS -- Controller Status */
116 #define	NVME_CSTS_SHN_OCCURING	1	/* Shutdown Processing Occuring */
117 #define	NVME_CSTS_SHN_COMPLETE	2	/* Shutdown Processing Complete */
118 
119 typedef union {
120 	struct {
121 		uint32_t csts_rdy:1;	/* Ready */
122 		uint32_t csts_cfs:1;	/* Controller Fatal Status */
123 		uint32_t csts_shst:2;	/* Shutdown Status */
124 		uint32_t csts_nssro:1;	/* NVM Subsystem Reset Occured */
125 		uint32_t csts_pp:1;	/* Processing Paused */
126 		uint32_t csts_rsvd:26;
127 	} b;
128 	uint32_t r;
129 } nvme_reg_csts_t;
130 
131 /* NSSR -- NVM Subsystem Reset */
132 #define	NVME_NSSR_NSSRC	0x4e564d65	/* NSSR magic value */
133 typedef uint32_t nvme_reg_nssr_t;
134 
135 /* AQA -- Admin Queue Attributes */
136 typedef union {
137 	struct {
138 		uint16_t aqa_asqs:12;	/* Admin Submission Queue Size */
139 		uint16_t aqa_rsvd1:4;
140 		uint16_t aqa_acqs:12;	/* Admin Completion Queue Size */
141 		uint16_t aqa_rsvd2:4;
142 	} b;
143 	uint32_t r;
144 } nvme_reg_aqa_t;
145 
146 /*
147  * The spec specifies the lower 12 bits of ASQ and ACQ as reserved, which is
148  * probably a specification bug. The full 64bit regs are used as base address,
149  * and the lower bits must be zero to ensure alignment on the page size
150  * specified in CC.MPS.
151  */
152 /* ASQ -- Admin Submission Queue Base Address */
153 typedef uint64_t nvme_reg_asq_t;	/* Admin Submission Queue Base */
154 
155 /* ACQ -- Admin Completion Queue Base Address */
156 typedef uint64_t nvme_reg_acq_t;	/* Admin Completion Queue Base */
157 
158 /* CMBLOC - Controller Memory Buffer Location */
159 typedef union {
160 	struct {
161 		uint32_t cmbloc_bir:3;		/* Base Indicator Register */
162 		uint32_t cmbloc_rsvd:9;
163 		uint32_t cmbloc_ofst:20;	/* Offset */
164 	} b;
165 	uint32_t r;
166 } nvme_reg_cmbloc_t;
167 
168 /* CMBSZ - Controller Memory Buffer Size */
169 typedef union {
170 	struct {
171 		uint32_t cmbsz_sqs:1;	/* Submission Queue Support */
172 		uint32_t cmbsz_cqs:1;	/* Completion Queue Support */
173 		uint32_t cmbsz_lists:1;	/* PRP SGL List Support */
174 		uint32_t cmbsz_rds:1;	/* Read Data Support */
175 		uint32_t cmbsz_wds:1;	/* Write Data Support */
176 		uint32_t cmbsz_rsvd:3;
177 		uint32_t cmbsz_szu:4;	/* Size Units */
178 		uint32_t cmbsz_sz:20;	/* Size */
179 	} b;
180 	uint32_t r;
181 } nvme_reg_cmbsz_t;
182 
183 /* BPINFO - Boot Partition Information */
184 typedef union {
185 	struct {
186 		uint32_t bpinfo_bpsz:15;	/* Boot Partition Size */
187 		uint32_t bpinfo_rsvd:9;
188 		uint32_t bpinfo_brs:2;		/* Boot Read Status */
189 		uint32_t bpinfo_rsvd2:5;
190 		uint32_t bpinfo_abpid:1;	/* Active Boot Partition ID */
191 	} b;
192 	uint32_t r;
193 } nvme_reg_bpinfo_t;
194 
195 /* BPRSEL - Boot Partition Read Select */
196 typedef union {
197 	struct {
198 		uint32_t bprsel_bprsz:10;	/* Boot Partition Read Size */
199 		uint32_t bprsel_bprof:20;	/* Boot Partition Read Offset */
200 		uint32_t bprsel_rsvd:1;
201 		uint32_t bprsel_bpid:1;		/* Boot Partition Identifier */
202 	} b;
203 	uint32_t r;
204 } nvme_reg_bprsel_t;
205 
206 /* BPMBL - Boot Partition Memory Location Buffer Location */
207 typedef uint64_t nvme_reg_bpbml_t;	/* Memory Buffer Base Address */
208 
209 /* SQyTDBL -- Submission Queue y Tail Doorbell */
210 typedef union {
211 	struct {
212 		uint16_t sqtdbl_sqt;	/* Submission Queue Tail */
213 		uint16_t sqtdbl_rsvd;
214 	} b;
215 	uint32_t r;
216 } nvme_reg_sqtdbl_t;
217 
218 /* CQyHDBL -- Completion Queue y Head Doorbell */
219 typedef union {
220 	struct {
221 		uint16_t cqhdbl_cqh;	/* Completion Queue Head */
222 		uint16_t cqhdbl_rsvd;
223 	} b;
224 	uint32_t r;
225 } nvme_reg_cqhdbl_t;
226 
227 /*
228  * NVMe submission queue entries
229  */
230 
231 /* NVMe scatter/gather list descriptor */
232 typedef struct {
233 	uint64_t sgl_addr;		/* Address */
234 	uint32_t sgl_len;		/* Length */
235 	uint8_t sgl_rsvd[3];
236 	uint8_t sgl_zero:4;
237 	uint8_t sgl_type:4;		/* SGL descriptor type */
238 } nvme_sgl_t;
239 
240 /* NVMe SGL descriptor type */
241 #define	NVME_SGL_DATA_BLOCK	0
242 #define	NVME_SGL_BIT_BUCKET	1
243 #define	NVME_SGL_SEGMENT	2
244 #define	NVME_SGL_LAST_SEGMENT	3
245 #define	NVME_SGL_VENDOR		0xf
246 
247 /* NVMe submission queue entry */
248 typedef struct {
249 	uint8_t sqe_opc;		/* Opcode */
250 	uint8_t sqe_fuse:2;		/* Fused Operation */
251 	uint8_t sqe_rsvd:5;
252 	uint8_t sqe_psdt:1;		/* PRP or SGL for Data Transfer */
253 	uint16_t sqe_cid;		/* Command Identifier */
254 	uint32_t sqe_nsid;		/* Namespace Identifier */
255 	uint64_t sqe_rsvd1;
256 	union {
257 		uint64_t m_ptr;		/* Metadata Pointer */
258 		uint64_t m_sglp;	/* Metadata SGL Segment Pointer */
259 	} sqe_m;
260 	union {
261 		uint64_t d_prp[2];	/* Physical Page Region Entries 1 & 2 */
262 		nvme_sgl_t d_sgl;	/* SGL Entry 1 */
263 	} sqe_dptr;			/* Data Pointer */
264 	uint32_t sqe_cdw10;		/* Number of Dwords in Data Transfer */
265 	uint32_t sqe_cdw11;		/* Number of Dwords in Metadata Xfer */
266 	uint32_t sqe_cdw12;
267 	uint32_t sqe_cdw13;
268 	uint32_t sqe_cdw14;
269 	uint32_t sqe_cdw15;
270 } nvme_sqe_t;
271 
272 /* NVMe admin command opcodes */
273 #define	NVME_OPC_DELETE_SQUEUE	0x0
274 #define	NVME_OPC_CREATE_SQUEUE	0x1
275 #define	NVME_OPC_GET_LOG_PAGE	0x2
276 #define	NVME_OPC_DELETE_CQUEUE	0x4
277 #define	NVME_OPC_CREATE_CQUEUE	0x5
278 #define	NVME_OPC_IDENTIFY	0x6
279 #define	NVME_OPC_ABORT		0x8
280 #define	NVME_OPC_SET_FEATURES	0x9
281 #define	NVME_OPC_GET_FEATURES	0xa
282 #define	NVME_OPC_ASYNC_EVENT	0xc
283 #define	NVME_OPC_NS_MGMT	0xd	/* 1.2 */
284 #define	NVME_OPC_FW_ACTIVATE	0x10
285 #define	NVME_OPC_FW_IMAGE_LOAD	0x11
286 #define	NVME_OPC_SELF_TEST	0x14	/* 1.3 */
287 #define	NVME_OPC_NS_ATTACH	0x15	/* 1.2 */
288 #define	NVME_OPC_KEEP_ALIVE	0x18	/* 1.3 */
289 #define	NVME_OPC_DIRECTIVE_SEND	0x19	/* 1.3 */
290 #define	NVME_OPC_DIRECTIVE_RECV	0x1A	/* 1.3 */
291 #define	NVME_OPC_VIRT_MGMT	0x1C	/* 1.3 */
292 #define	NVME_OPC_NVMEMI_SEND	0x1D	/* 1.3 */
293 #define	NVME_OPC_NVMEMI_RECV	0x1E	/* 1.3 */
294 #define	NVME_OPC_DB_CONFIG	0x7C	/* 1.3 */
295 
296 /* NVMe NVM command set specific admin command opcodes */
297 #define	NVME_OPC_NVM_FORMAT	0x80
298 #define	NVME_OPC_NVM_SEC_SEND	0x81
299 #define	NVME_OPC_NVM_SEC_RECV	0x82
300 
301 /* NVMe NVM command opcodes */
302 #define	NVME_OPC_NVM_FLUSH	0x0
303 #define	NVME_OPC_NVM_WRITE	0x1
304 #define	NVME_OPC_NVM_READ	0x2
305 #define	NVME_OPC_NVM_WRITE_UNC	0x4
306 #define	NVME_OPC_NVM_COMPARE	0x5
307 #define	NVME_OPC_NVM_WRITE_ZERO	0x8
308 #define	NVME_OPC_NVM_DSET_MGMT	0x9
309 #define	NVME_OPC_NVM_RESV_REG	0xd
310 #define	NVME_OPC_NVM_RESV_REPRT	0xe
311 #define	NVME_OPC_NVM_RESV_ACQ	0x11
312 #define	NVME_OPC_NVM_RESV_REL	0x12
313 
314 /*
315  * NVMe completion queue entry
316  */
317 typedef struct {
318 	uint32_t cqe_dw0;		/* Command Specific */
319 	uint32_t cqe_rsvd1;
320 	uint16_t cqe_sqhd;		/* SQ Head Pointer */
321 	uint16_t cqe_sqid;		/* SQ Identifier */
322 	uint16_t cqe_cid;		/* Command Identifier */
323 	nvme_cqe_sf_t cqe_sf;		/* Status Field */
324 } nvme_cqe_t;
325 
326 /*
327  * NVMe Asynchronous Event Request
328  */
329 #define	NVME_ASYNC_TYPE_ERROR		0x0	/* Error Status */
330 #define	NVME_ASYNC_TYPE_HEALTH		0x1	/* SMART/Health Status */
331 #define	NVME_ASYNC_TYPE_NOTICE		0x2	/* Notice (1.2) */
332 #define	NVME_ASYNC_TYPE_VENDOR		0x7	/* Vendor specific */
333 
334 #define	NVME_ASYNC_ERROR_INV_SQ		0x0	/* Invalid Submission Queue */
335 #define	NVME_ASYNC_ERROR_INV_DBL	0x1	/* Invalid Doorbell Write */
336 #define	NVME_ASYNC_ERROR_DIAGFAIL	0x2	/* Diagnostic Failure */
337 #define	NVME_ASYNC_ERROR_PERSISTENT	0x3	/* Persistent Internal Error */
338 #define	NVME_ASYNC_ERROR_TRANSIENT	0x4	/* Transient Internal Error */
339 #define	NVME_ASYNC_ERROR_FW_LOAD	0x5	/* Firmware Image Load Error */
340 
341 #define	NVME_ASYNC_HEALTH_RELIABILITY	0x0	/* Device Reliability */
342 #define	NVME_ASYNC_HEALTH_TEMPERATURE	0x1	/* Temp. Above Threshold */
343 #define	NVME_ASYNC_HEALTH_SPARE		0x2	/* Spare Below Threshold */
344 
345 /* NVMe 1.2 */
346 #define	NVME_ASYNC_NOTICE_NS_CHANGE	0x0	/* Namespace attribute change */
347 #define	NVME_ASYNC_NOTICE_FW_ACTIVATE	0x1	/* Firmware activation start */
348 /* NVMe 1.3 */
349 #define	NVME_ASYNC_NOTICE_TELEMETRY	0x2	/* Telemetry log changed */
350 /* NVMe 1.4 */
351 #define	NVME_ASYNC_NOTICE_NS_ASYMM	0x3	/* Asymm. NS access change */
352 #define	NVME_ASYNC_NOTICE_LATENCYLOG	0x4	/* Pred. Latency log change */
353 #define	NVME_ASYNC_NOTICE_LBASTATUS	0x5	/* LBA status alert */
354 #define	NVME_ASYNC_NOTICE_ENDURANCELOG	0x6	/* Endurance log change */
355 
356 typedef union {
357 	struct {
358 		uint8_t ae_type:3;		/* Asynchronous Event Type */
359 		uint8_t ae_rsvd1:5;
360 		uint8_t ae_info;		/* Asynchronous Event Info */
361 		uint8_t ae_logpage;		/* Associated Log Page */
362 		uint8_t ae_rsvd2;
363 	} b;
364 	uint32_t r;
365 } nvme_async_event_t;
366 
367 /*
368  * NVMe Create Completion/Submission Queue
369  */
370 typedef union {
371 	struct {
372 		uint16_t q_qid;			/* Queue Identifier */
373 		uint16_t q_qsize;		/* Queue Size */
374 	} b;
375 	uint32_t r;
376 } nvme_create_queue_dw10_t;
377 
378 typedef union {
379 	struct {
380 		uint16_t cq_pc:1;		/* Physically Contiguous */
381 		uint16_t cq_ien:1;		/* Interrupts Enabled */
382 		uint16_t cq_rsvd:14;
383 		uint16_t cq_iv;			/* Interrupt Vector */
384 	} b;
385 	uint32_t r;
386 } nvme_create_cq_dw11_t;
387 
388 typedef union {
389 	struct {
390 		uint16_t sq_pc:1;		/* Physically Contiguous */
391 		uint16_t sq_qprio:2;		/* Queue Priority */
392 		uint16_t sq_rsvd:13;
393 		uint16_t sq_cqid;		/* Completion Queue ID */
394 	} b;
395 	uint32_t r;
396 } nvme_create_sq_dw11_t;
397 
398 /*
399  * NVMe Abort Command
400  */
401 typedef union {
402 	struct {
403 		uint16_t ac_sqid;	/* Submission Queue ID */
404 		uint16_t ac_cid;	/* Command ID */
405 	} b;
406 	uint32_t r;
407 } nvme_abort_cmd_t;
408 
409 /*
410  * NVMe Get Log Page. dw12/13 are the lower and upper halves of the 64-bit
411  * offset field respectively in bytes. These must be dword aligned. The offset
412  * was added in NVMe v1.2, but requires controller support.
413  */
414 typedef union {
415 	struct {
416 		uint8_t lp_lid;		/* Log Page Identifier */
417 		/*
418 		 * The log-specific field was introduced as a 4-bit field in
419 		 * NVMe 1.3. It was extended to be a 7-bit field in NVMe 2.0 and
420 		 * renamed log-specific parameter.
421 		 */
422 		uint8_t lp_lsp:7;
423 		uint8_t lp_rae:1;	/* Retain Async Event  v1.3 */
424 		/*
425 		 * This is the lower number of dwords. This was changed in NVMe
426 		 * v1.2 to be split between this field and dw11. In NVMe 1.0/1.1
427 		 * this was only 12 bits long.
428 		 */
429 		uint16_t lp_lnumdl;	/* Number of Dwords */
430 	} b;
431 	uint32_t r;
432 } nvme_getlogpage_dw10_t;
433 
434 typedef union {
435 	struct {
436 		uint16_t lp_numdu;	/* Number of dwords v1.2 */
437 		uint16_t lp_lsi;	/* Log Specific Field v1.3 */
438 	} b;
439 	uint32_t r;
440 } nvme_getlogpage_dw11_t;
441 
442 typedef union {
443 	struct {
444 		uint8_t lp_uuid:7;	/* UUID Index v1.4 */
445 		uint8_t lp_rsvd1:1;
446 		uint8_t lp_rsvd2;
447 		uint8_t lp_rsvd3:7;
448 		uint8_t lp_ot:1;	/* Offset Type v2.0 */
449 		uint8_t lp_csi;		/* Command Set Identifier v2.0 */
450 	} b;
451 	uint32_t r;
452 } nvme_getlogpage_dw14_t;
453 
454 /*
455  * dword11 values for the dataset management command. Note that the dword11
456  * attributes are distinct from the context attributes (nr_ctxattr) values
457  * for an individual range (of the context attribute values defined by the NVMe
458  * spec, none are currently used by the NVMe driver).
459  */
460 #define	NVME_DSET_MGMT_ATTR_OPT_READ	0x01
461 #define	NVME_DSET_MGMT_ATTR_OPT_WRITE	0x02
462 #define	NVME_DSET_MGMT_ATTR_DEALLOCATE	0x04
463 
464 #define	NVME_DSET_MGMT_MAX_RANGES	256
465 typedef struct {
466 	uint32_t	nr_ctxattr;
467 	uint32_t	nr_len;
468 	uint64_t	nr_lba;
469 } nvme_range_t;
470 
471 /*
472  * NVMe Identify Command
473  */
474 typedef union {
475 	struct {
476 		/*
477 		 * The controller or namespace structure (CNS). This field was
478 		 * originally a single bit wide in NVMe 1.0. It was two bits
479 		 * wide in NVMe 1.1 and was increased to 8 bits in NVMe 1.2.
480 		 */
481 		uint8_t id_cns;
482 		uint8_t id_rsvd0;
483 		uint16_t id_cntid;	/* Controller ID, NVMe 1.2 */
484 	} b;
485 	uint32_t r;
486 } nvme_identify_dw10_t;
487 
488 #ifdef __cplusplus
489 }
490 #endif
491 
492 #pragma pack() /* pack(1) */
493 
494 #endif /* _NVME_REG_H */
495