xref: /illumos-gate/usr/src/uts/intel/io/amdzen/zen_umc.h (revision 71815ce7)
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 2022 Oxide Computer Company
14  */
15 
16 #ifndef _ZEN_UMC_H
17 #define	_ZEN_UMC_H
18 
19 /*
20  * This file contains definitions that are used to manage and decode the Zen UMC
21  * state.
22  */
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 #include <sys/stdint.h>
29 #include <sys/sunddi.h>
30 #include <sys/nvpair.h>
31 #include <amdzen_client.h>
32 
33 /*
34  * This is the maximum number of DRAM rules that we expect any supported device
35  * to have here. The actual number may be less. These are rules that come from a
36  * DF CCM.
37  */
38 #define	ZEN_UMC_MAX_DRAM_RULES	20
39 
40 /*
41  * This is the maximum number of rules that we expect any system to actually
42  * have for each UMC.
43  */
44 #define	ZEN_UMC_MAX_CS_RULES	4
45 
46 /*
47  * This is the maximum number of DFs that we expect to encounter in a given
48  * platform. This number comes from the Naples generation, where there were up
49  * to 4 per socket, 2 sockets per machine, so 8 total. In subsequent generations
50  * there is only a single 1 per socket.
51  */
52 #define	ZEN_UMC_MAX_DFS	8
53 
54 /*
55  * This indicates the maximum number of UMC DF nodes that we expect to
56  * encounter.
57  */
58 #define	ZEN_UMC_MAX_UMCS	12
59 
60 /*
61  * This indicates the maximum number of DRAM offset rules that can exist in a
62  * platform. Note, this is directly tied to the maximum number of CS rules.
63  */
64 #define	ZEN_UMC_MAX_DRAM_OFFSET	(ZEN_UMC_MAX_CS_RULES - 1)
65 
66 /*
67  * This indicates the maximum number of remap rule sets and corresponding
68  * entries that can exist. Milan's max is smaller than the current overall DFv4
69  * maximum.
70  */
71 #define	ZEN_UMC_MAX_CS_REMAPS		4
72 #define	ZEN_UMC_MAX_REMAP_ENTS		16
73 #define	ZEN_UMC_MILAN_CS_NREMAPS	2
74 #define	ZEN_UMC_MILAN_REMAP_ENTS	12
75 #define	ZEN_UMC_REMAP_PER_REG		8
76 
77 /*
78  * DRAM Channel related maximums.
79  */
80 #define	ZEN_UMC_MAX_DIMMS		2
81 #define	ZEN_UMC_MAX_CS_PER_DIMM		2
82 #define	ZEN_UMC_MAX_CS_BITS		2
83 #define	ZEN_UMC_MAX_CHAN_BASE		2
84 #define	ZEN_UMC_MAX_CHAN_MASK		2
85 #define	ZEN_UMC_MAX_BANK_BITS		5
86 #define	ZEN_UMC_MAX_COL_BITS		16
87 #define	ZEN_UMC_MAX_RM_BITS		4
88 #define	ZEN_UMC_MAX_COLSEL_PER_REG	8
89 
90 #define	ZEN_UMC_DDR4_CHAN_NMASKS	1
91 
92 /*
93  * DRAM Channel hash maximums. Surprisingly enough, the DDR4 and DDR5 maximums
94  * are the same; however, in exchange what hashes are actually implemented
95  * varies.
96  */
97 #define	ZEN_UMC_MAX_CHAN_BANK_HASH	5
98 #define	ZEN_UMC_MAX_CHAN_RM_HASH	3
99 #define	ZEN_UMC_MAX_CHAN_CS_HASH	2
100 
101 /*
102  * This is the logical set of different channel interleaving rules that we
103  * support today in the driver. The actual values of the enumeration do not
104  * overlap at all with hardware. Do not use these to try and marry up against
105  * values from the DF itself.
106  *
107  * Note, these values are also encoded in the private mc decoder dumps that we
108  * can produce. If these values change, please take care of ensuring
109  * compatibility for others who may be consuming this. Appending to this list
110  * should be OK.
111  */
112 typedef enum df_chan_ileave {
113 	DF_CHAN_ILEAVE_1CH	= 0,
114 	DF_CHAN_ILEAVE_2CH,
115 	DF_CHAN_ILEAVE_4CH,
116 	DF_CHAN_ILEAVE_6CH,
117 	DF_CHAN_ILEAVE_8CH,
118 	DF_CHAN_ILEAVE_16CH,
119 	DF_CHAN_ILEAVE_32CH,
120 	DF_CHAN_ILEAVE_COD4_2CH,
121 	DF_CHAN_ILEAVE_COD2_4CH,
122 	DF_CHAN_ILEAVE_COD1_8CH,
123 	DF_CHAN_ILEAVE_NPS4_2CH,
124 	DF_CHAN_ILEAVE_NPS2_4CH,
125 	DF_CHAN_ILEAVE_NPS1_8CH,
126 	DF_CHAN_ILEAVE_NPS4_3CH,
127 	DF_CHAN_ILEAVE_NPS2_6CH,
128 	DF_CHAN_ILEAVE_NPS1_12CH,
129 	DF_CHAN_ILEAVE_NPS2_5CH,
130 	DF_CHAN_ILEAVE_NPS1_10CH
131 } df_chan_ileave_t;
132 
133 /*
134  * This is a collection of logical flags that we use to cover attributes of a
135  * DRAM rule.
136  */
137 typedef enum df_dram_flags {
138 	/*
139 	 * Used to indicate that the contents of the rule are actually valid and
140 	 * should be considered. Many rules can be unused in hardware.
141 	 */
142 	DF_DRAM_F_VALID		= 1 << 0,
143 	/*
144 	 * Indicates that the DRAM hole is active for this particular rule. If
145 	 * this flag is set and the hole is valid in the DF, then we need to
146 	 * take the actual DRAM hole into account.
147 	 */
148 	DF_DRAM_F_HOLE		= 1 << 1,
149 	/*
150 	 * These next three are used to indicate when hashing is going on, which
151 	 * bits to use. These are for 64K, 2M, and 1G parts of addresses
152 	 * respectively.
153 	 */
154 	DF_DRAM_F_HASH_16_18	= 1 << 2,
155 	DF_DRAM_F_HASH_21_23	= 1 << 3,
156 	DF_DRAM_F_HASH_30_32	= 1 << 4,
157 	/*
158 	 * Indicates that this rule should have remap processing and the remap
159 	 * target is valid. If the DF_DRAM_F_REMAP_SOCK flag is set, this
160 	 * indicates that the processing is based on socket versus a particular
161 	 * entry.
162 	 */
163 	DF_DRAM_F_REMAP_EN	= 1 << 5,
164 	DF_DRAM_F_REMAP_SOCK	= 1 << 6
165 } df_dram_flags_t;
166 
167 /*
168  * This represents a single offset value for a channel. This is used when
169  * applying normalization.
170  */
171 typedef struct chan_offset {
172 	uint32_t	cho_raw;
173 	boolean_t	cho_valid;
174 	uint64_t	cho_offset;
175 } chan_offset_t;
176 
177 /*
178  * This structure represents a single DRAM rule, no matter where it shows up.
179  * This smooths over the differences between generations.
180  */
181 typedef struct df_dram_rule {
182 	uint32_t		ddr_raw_base;
183 	uint32_t		ddr_raw_limit;
184 	uint32_t		ddr_raw_ctrl;
185 	uint32_t		ddr_raw_ileave;
186 	df_dram_flags_t		ddr_flags;
187 	uint64_t		ddr_base;
188 	uint64_t		ddr_limit;
189 	uint16_t		ddr_dest_fabid;
190 	uint8_t			ddr_sock_ileave_bits;
191 	uint8_t			ddr_die_ileave_bits;
192 	uint8_t			ddr_addr_start;
193 	uint8_t			ddr_remap_ent;
194 	df_chan_ileave_t	ddr_chan_ileave;
195 } df_dram_rule_t;
196 
197 typedef struct umc_dimm_base {
198 	uint64_t	udb_base;
199 	boolean_t	udb_valid;
200 } umc_dimm_base_t;
201 
202 typedef enum umc_dimm_type {
203 	UMC_DIMM_T_UNKNOWN,
204 	UMC_DIMM_T_DDR4,
205 	UMC_DIMM_T_LPDDR4,
206 	UMC_DIMM_T_DDR5,
207 	UMC_DIMM_T_LPDDR5
208 } umc_dimm_type_t;
209 
210 typedef enum umc_dimm_width {
211 	UMC_DIMM_W_X4,
212 	UMC_DIMM_W_X8,
213 	UMC_DIMM_W_X16,
214 } umc_dimm_width_t;
215 
216 typedef enum umc_dimm_kind {
217 	UMC_DIMM_K_UDIMM,
218 	UMC_DIMM_K_RDIMM,
219 	UMC_DIMM_K_LRDIMM,
220 	UMC_DIMM_K_3DS_RDIMM
221 } umc_dimm_kind_t;
222 
223 typedef enum umc_dimm_flags {
224 	/*
225 	 * This flag indicates that this DIMM should be used for decoding
226 	 * purposes. It basically means that there is at least one chip-select
227 	 * decoding register that has been enabled. Unfortunately, we don't have
228 	 * a good way right now of distinguishing between a DIMM being present
229 	 * and being usable. This likely needs to be re-evaluated when we
230 	 * consider how we present things to topo. We may be able to pull this
231 	 * out of the clock disable logic.
232 	 */
233 	UMC_DIMM_F_VALID	= 1 << 0,
234 } umc_dimm_flags_t;
235 
236 /*
237  * A DIMM may have one or more ranks, which is an independent logical item that
238  * is activated by a 'chip-select' signal on a DIMM (e.g. CS_L[1:0]). In a given
239  * channel, AMD always has two instances of a 'chip-select' data structure.
240  * While these have a 1:1 correspondence in the case of single and dual rank
241  * DIMMs, in the case where there are more, then rank multiplication rules are
242  * used to determine which of the additional chip and chip-select signals to
243  * actually drive on the bus. But still, there are only up to two of these
244  * structures. To match AMD terminology we call these a 'chip-select' or
245  * 'umc_cs_t'.
246  *
247  * The amount of information that exists on a per-chip-select and per-DIMM basis
248  * varies between the different memory controller generations. As such, we
249  * normalize things such that a given chip-select always has all of the
250  * information related to it, duplicating it in the DDR4 case.
251  *
252  * While DDR5 adds the notion of sub-channels, a single chip-select is used to
253  * cover both sub-channels and instead a bit in the normalized address (and
254  * hashing) is used to determine which sub-channel to active. So while hardware
255  * actually has different chip-select lines for each sub-channel they are not
256  * represented that way in the UMC.
257  */
258 typedef struct umc_cs {
259 	umc_dimm_base_t		ucs_base;
260 	umc_dimm_base_t		ucs_sec;
261 	uint64_t		ucs_base_mask;
262 	uint64_t		ucs_sec_mask;
263 	uint8_t			ucs_nbanks;
264 	uint8_t			ucs_ncol;
265 	uint8_t			ucs_nrow_lo;
266 	uint8_t			ucs_nrow_hi;
267 	uint8_t			ucs_nrm;
268 	uint8_t			ucs_nbank_groups;
269 	uint8_t			ucs_cs_xor;
270 	uint8_t			ucs_row_hi_bit;
271 	uint8_t			ucs_row_low_bit;
272 	uint8_t			ucs_bank_bits[ZEN_UMC_MAX_BANK_BITS];
273 	uint8_t			ucs_col_bits[ZEN_UMC_MAX_COL_BITS];
274 	uint8_t			ucs_inv_msbs;
275 	uint8_t			ucs_rm_bits[ZEN_UMC_MAX_RM_BITS];
276 	uint8_t			ucs_inv_msbs_sec;
277 	uint8_t			ucs_rm_bits_sec[ZEN_UMC_MAX_RM_BITS];
278 	uint8_t			ucs_subchan;
279 } umc_cs_t;
280 
281 /*
282  * This structure represents information about a DIMM. Most of the interesting
283  * stuff is on the umc_cs_t up above, which is the logical 'chip-select' that
284  * AMD implements in the UMC.
285  *
286  * When we come back and add topo glue for the driver, we should consider adding
287  * the following information here and in the channel:
288  *
289  *  o Configured DIMM speed
290  *  o Channel capable speed
291  *  o Calculated size
292  *  o A way to map this DIMM to an SMBIOS / SPD style entry
293  */
294 typedef struct umc_dimm {
295 	umc_dimm_flags_t	ud_flags;
296 	umc_dimm_width_t	ud_width;
297 	umc_dimm_type_t		ud_type;
298 	umc_dimm_kind_t		ud_kind;
299 	uint32_t		ud_dimmno;
300 	uint32_t		ud_dimmcfg_raw;
301 	umc_cs_t		ud_cs[ZEN_UMC_MAX_CS_PER_DIMM];
302 } umc_dimm_t;
303 
304 typedef enum umc_chan_flags {
305 	/*
306 	 * Indicates that the channel has enabled ECC logic.
307 	 */
308 	UMC_CHAN_F_ECC_EN	= 1 << 0,
309 	/*
310 	 * We believe that this indicates some amount of the AMD SEV encryption
311 	 * is ongoing, leveraging some of the page-table control.
312 	 */
313 	UMC_CHAN_F_ENCR_EN	= 1 << 1,
314 	/*
315 	 * Indicates that the channel is employing data scrambling. This is
316 	 * basically what folks have called Transparent Shared Memory
317 	 * Encryption.
318 	 */
319 	UMC_CHAN_F_SCRAMBLE_EN	= 1 << 2
320 } umc_chan_flags_t;
321 
322 typedef struct umc_bank_hash {
323 	uint32_t	ubh_row_xor;
324 	uint32_t	ubh_col_xor;
325 	boolean_t	ubh_en;
326 } umc_bank_hash_t;
327 
328 typedef struct umc_addr_hash {
329 	uint64_t	uah_addr_xor;
330 	boolean_t	uah_en;
331 } umc_addr_hash_t;
332 
333 typedef struct umc_pc_hash {
334 	uint32_t	uph_row_xor;
335 	uint32_t	uph_col_xor;
336 	uint8_t		uph_bank_xor;
337 	boolean_t	uph_en;
338 } umc_pc_hash_t;
339 
340 typedef enum umc_chan_hash_flags {
341 	UMC_CHAN_HASH_F_BANK	= 1 << 0,
342 	UMC_CHAN_HASH_F_RM	= 1 << 1,
343 	UMC_CHAN_HASH_F_PC	= 1 << 2,
344 	UMC_CHAN_HASH_F_CS	= 1 << 3,
345 } umc_chan_hash_flags_t;
346 
347 typedef struct umc_chan_hash {
348 	umc_chan_hash_flags_t	uch_flags;
349 	umc_bank_hash_t		uch_bank_hashes[ZEN_UMC_MAX_CHAN_BANK_HASH];
350 	umc_addr_hash_t		uch_rm_hashes[ZEN_UMC_MAX_CHAN_RM_HASH];
351 	umc_addr_hash_t		uch_cs_hashes[ZEN_UMC_MAX_CHAN_CS_HASH];
352 	umc_pc_hash_t		uch_pc_hash;
353 } umc_chan_hash_t;
354 
355 /*
356  * This structure represents the overall memory channel. There is a 1:1
357  * relationship between these structures and discover UMC hardware entities on
358  * the data fabric. Note, these always exist regardless of whether the channels
359  * are actually implemented on a PCB or not.
360  */
361 typedef struct zen_umc_chan {
362 	umc_chan_flags_t	chan_flags;
363 	uint32_t		chan_fabid;
364 	uint32_t		chan_instid;
365 	uint32_t		chan_logid;
366 	uint32_t		chan_nrules;
367 	uint32_t		chan_umccfg_raw;
368 	uint32_t		chan_datactl_raw;
369 	uint32_t		chan_eccctl_raw;
370 	uint32_t		chan_umccap_raw;
371 	uint32_t		chan_umccap_hi_raw;
372 	uint32_t		chan_np2_raw;
373 	uint32_t		chan_np2_space0;
374 	df_dram_rule_t		chan_rules[ZEN_UMC_MAX_CS_RULES];
375 	chan_offset_t		chan_offsets[ZEN_UMC_MAX_DRAM_OFFSET];
376 	umc_dimm_t		chan_dimms[ZEN_UMC_MAX_DIMMS];
377 	umc_chan_hash_t		chan_hash;
378 } zen_umc_chan_t;
379 
380 typedef struct zen_umc_cs_remap {
381 	uint_t		csr_nremaps;
382 	uint16_t	csr_remaps[ZEN_UMC_MAX_REMAP_ENTS];
383 } zen_umc_cs_remap_t;
384 
385 typedef enum zen_umc_df_flags {
386 	/*
387 	 * Indicates that the DRAM Hole is valid and in use.
388 	 */
389 	ZEN_UMC_DF_F_HOLE_VALID	= 1 << 0,
390 	/*
391 	 * These next three are used to indicate when hashing is going on, which
392 	 * bits to use. These are for 64K, 2M, and 1G parts of addresses
393 	 * respectively.
394 	 */
395 	ZEN_UMC_DF_F_HASH_16_18	= 1 << 1,
396 	ZEN_UMC_DF_F_HASH_21_23	= 1 << 2,
397 	ZEN_UMC_DF_F_HASH_30_32	= 1 << 3
398 } zen_umc_df_flags_t;
399 
400 typedef struct zen_umc_df {
401 	zen_umc_df_flags_t	zud_flags;
402 	uint_t			zud_dfno;
403 	uint_t			zud_ccm_inst;
404 	uint_t			zud_dram_nrules;
405 	uint_t			zud_nchan;
406 	uint_t			zud_cs_nremap;
407 	uint32_t		zud_hole_raw;
408 	uint32_t		zud_glob_ctl_raw;
409 	uint64_t		zud_hole_base;
410 	df_dram_rule_t		zud_rules[ZEN_UMC_MAX_DRAM_RULES];
411 	zen_umc_cs_remap_t	zud_remap[ZEN_UMC_MAX_CS_REMAPS];
412 	zen_umc_chan_t		zud_chan[ZEN_UMC_MAX_UMCS];
413 } zen_umc_df_t;
414 
415 typedef enum zen_umc_umc_style {
416 	ZEN_UMC_UMC_S_DDR4,
417 	ZEN_UMC_UMC_S_DDR4_APU,
418 	ZEN_UMC_UMC_S_DDR5,
419 	ZEN_UMC_UMC_S_DDR5_APU
420 } zen_umc_umc_style_t;
421 
422 typedef enum zen_umc_fam_flags {
423 	/*
424 	 * Indicates that there's an indirection table for the destinations of
425 	 * target rules.
426 	 */
427 	ZEN_UMC_FAM_F_TARG_REMAP	= 1 << 0,
428 	/*
429 	 * Indicates that non-power of two interleave rules are supported and
430 	 * that we need additional register configuration.
431 	 */
432 	ZEN_UMC_FAM_F_NP2		= 1 << 1,
433 	/*
434 	 * Indicates that the DF hashing rules to configure COD hashes need to
435 	 * be checked.
436 	 */
437 	ZEN_UMC_FAM_F_NORM_HASH		= 1 << 2,
438 	/*
439 	 * In DDR4 this indicates presence of the HashRM and in DDR5 the
440 	 * AddrHash.
441 	 */
442 	ZEN_UMC_FAM_F_UMC_HASH		= 1 << 3,
443 	/*
444 	 * Indicates support for extended UMC registers for larger addresses.
445 	 * Generally on Server parts.
446 	 */
447 	ZEN_UMC_FAM_F_UMC_EADDR		= 1 << 4,
448 	/*
449 	 * Indicates that CS decoder supports an XOR function.
450 	 */
451 	ZEN_UMC_FAM_F_CS_XOR		= 1 << 5
452 } zen_umc_fam_flags_t;
453 
454 /*
455  * This structure is meant to contain per SoC family (not CPUID family)
456  * information. This is stuff that we basically need to encode about the
457  * processor itself and relates to its limits, the style it operates in, the
458  * way it works, etc.
459  */
460 typedef struct zen_umc_fam_data {
461 	zen_family_t		zufd_family;
462 	zen_umc_fam_flags_t	zufd_flags;
463 	uint8_t			zufd_dram_nrules;
464 	uint8_t			zufd_cs_nrules;
465 	zen_umc_umc_style_t	zufd_umc_style;
466 	umc_chan_hash_flags_t	zufd_chan_hash;
467 } zen_umc_fam_data_t;
468 
469 /*
470  * The top-level data structure for the system. This is a single structure that
471  * represents everything that could possibly exist and is filled in with what we
472  * actually discover.
473  */
474 typedef struct zen_umc {
475 	uint64_t umc_tom;
476 	uint64_t umc_tom2;
477 	dev_info_t *umc_dip;
478 	zen_family_t umc_family;
479 	df_rev_t umc_df_rev;
480 	const zen_umc_fam_data_t *umc_fdata;
481 	df_fabric_decomp_t umc_decomp;
482 	uint_t umc_ndfs;
483 	zen_umc_df_t umc_dfs[ZEN_UMC_MAX_DFS];
484 	/*
485 	 * This lock protects the data underneath here.
486 	 */
487 	kmutex_t umc_nvl_lock;
488 	nvlist_t *umc_decoder_nvl;
489 	char *umc_decoder_buf;
490 	size_t umc_decoder_len;
491 } zen_umc_t;
492 
493 typedef enum zen_umc_decode_failure {
494 	ZEN_UMC_DECODE_F_NONE = 0,
495 	/*
496 	 * Indicates that the address was not contained within the TOM and TOM2
497 	 * regions that indicate DRAM (or was in a reserved hole).
498 	 */
499 	ZEN_UMC_DECODE_F_OUTSIDE_DRAM,
500 	/*
501 	 * Indicates that we could not find a DF rule in the CCM rule that
502 	 * claims to honor this address.
503 	 */
504 	ZEN_UMC_DECODE_F_NO_DF_RULE,
505 	/*
506 	 * Indicates that trying to construct the interleave address to use
507 	 * would have led to an underflow somehow.
508 	 */
509 	ZEN_UMC_DECODE_F_ILEAVE_UNDERFLOW,
510 	/*
511 	 * Indicates that we do not currently support decoding the indicated
512 	 * channel interleave type.
513 	 */
514 	ZEN_UMC_DECODE_F_CHAN_ILEAVE_NOTSUP,
515 	/*
516 	 * Indicates that we found a COD hash rule that had a non-zero socket or
517 	 * die interleave, which isn't supported and we don't know how to
518 	 * decode.
519 	 */
520 	ZEN_UMC_DECODE_F_COD_BAD_ILEAVE,
521 	/*
522 	 * This is similar to the above, but indicates that we hit a bad NPS
523 	 * interleave rule instead of a COD.
524 	 */
525 	ZEN_UMC_DECODE_F_NPS_BAD_ILEAVE,
526 	/*
527 	 * Indicates that somehow we thought we should use a remap rule set that
528 	 * was beyond our capabilities.
529 	 */
530 	ZEN_UMC_DECODE_F_BAD_REMAP_SET,
531 	/*
532 	 * Indicates that we tried to find an index for the remap rules;
533 	 * however, the logical component ID was outside the range of the number
534 	 * of entries that we have.
535 	 */
536 	ZEN_UMC_DECODE_F_BAD_REMAP_ENTRY,
537 	/*
538 	 * Indicates that the remap rule had an invalid component bit set in its
539 	 * mask.
540 	 */
541 	ZEN_UMC_DECODE_F_REMAP_HAS_BAD_COMP,
542 	/*
543 	 * Indicates that we could not find a UMC with the fabric ID we thought
544 	 * we should have.
545 	 */
546 	ZEN_UMC_DECODE_F_CANNOT_MAP_FABID,
547 	/*
548 	 * Indicates that somehow the UMC we found did not actually contain a
549 	 * DRAM rule that covered our original PA.
550 	 */
551 	ZEN_UMC_DECODE_F_UMC_DOESNT_HAVE_PA,
552 	/*
553 	 * Indicates that we would have somehow underflowed the address
554 	 * calculations normalizing the system address.
555 	 */
556 	ZEN_UMC_DECODE_F_CALC_NORM_UNDERFLOW,
557 	/*
558 	 * Indicates that none of the UMC's chip-selects actually matched a base
559 	 * or secondary.
560 	 */
561 	ZEN_UMC_DECODE_F_NO_CS_BASE_MATCH
562 } zen_umc_decode_failure_t;
563 
564 /*
565  * This struct accumulates all of our decoding logic and states and we use it so
566  * it's easier for us to look at what's going on and the decisions that we made
567  * along the way.
568  */
569 typedef struct zen_umc_decoder {
570 	zen_umc_decode_failure_t	dec_fail;
571 	uint64_t			dec_fail_data;
572 	uint64_t			dec_pa;
573 	const zen_umc_df_t		*dec_df_rulesrc;
574 	uint32_t			dec_df_ruleno;
575 	const df_dram_rule_t		*dec_df_rule;
576 	uint64_t			dec_ilv_pa;
577 	/*
578 	 * These three values represent the IDs that we extract from the
579 	 * interleave address.
580 	 */
581 	uint32_t			dec_ilv_sock;
582 	uint32_t			dec_ilv_die;
583 	uint32_t			dec_ilv_chan;
584 	uint32_t			dec_ilv_fabid;
585 	uint32_t			dec_log_fabid;
586 	uint32_t			dec_remap_comp;
587 	uint32_t			dec_targ_fabid;
588 	const zen_umc_chan_t		*dec_umc_chan;
589 	uint32_t			dec_umc_ruleno;
590 	uint64_t			dec_norm_addr;
591 	const umc_dimm_t		*dec_dimm;
592 	const umc_cs_t			*dec_cs;
593 	boolean_t			dec_cs_sec;
594 	uint32_t			dec_dimm_col;
595 	uint32_t			dec_dimm_row;
596 	uint8_t				dec_log_csno;
597 	uint8_t				dec_dimm_bank;
598 	uint8_t				dec_dimm_bank_group;
599 	uint8_t				dec_dimm_subchan;
600 	uint8_t				dec_dimm_rm;
601 	uint8_t				dec_chan_csno;
602 	uint8_t				dec_dimm_no;
603 	uint8_t				dec_dimm_csno;
604 } zen_umc_decoder_t;
605 
606 /*
607  * Decoding and normalization routines.
608  */
609 extern boolean_t zen_umc_decode_pa(const zen_umc_t *, const uint64_t,
610     zen_umc_decoder_t *);
611 
612 /*
613  * Fabric ID utilities
614  */
615 extern boolean_t zen_fabric_id_valid_fabid(const df_fabric_decomp_t *,
616     const uint32_t);
617 extern boolean_t zen_fabric_id_valid_parts(const df_fabric_decomp_t *,
618     const uint32_t, const uint32_t, const uint32_t);
619 extern void zen_fabric_id_decompose(const df_fabric_decomp_t *, const uint32_t,
620     uint32_t *, uint32_t *, uint32_t *);
621 extern void zen_fabric_id_compose(const df_fabric_decomp_t *, const uint32_t,
622     const uint32_t, const uint32_t, uint32_t *);
623 
624 /*
625  * Encoding and decoding
626  */
627 extern nvlist_t *zen_umc_dump_decoder(zen_umc_t *);
628 extern boolean_t zen_umc_restore_decoder(nvlist_t *, zen_umc_t *);
629 
630 #ifdef __cplusplus
631 }
632 #endif
633 
634 #endif /* _ZEN_UMC_H */
635