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