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