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 2025 Oxide Computer Company 14 */ 15 16 /* 17 * Here we construct a more realistic DF situation where we have multiple rules. 18 * In particular, we use a DFv3 style configuration with a single die and 19 * socket. To make sense of the channel offset logic, we construct a system with 20 * two channels, one with 64 GiB and one one 8 GiB DIMMs. We basically 21 * interleave with the 16 GiB channel over the last 16 GiB of the 128 GiB 22 * channel. This requires us to therefore use the channel offset for the first 23 * channel to get it in a reasonable spot for the second rule. This also allows 24 * us to test what happens with multiple rules and ensure that we select the 25 * right one and when two rules map to one channel. 26 * 27 * Here, the hole is sized to 1.75 GiB. This is based on a system we saw that 28 * was set up this way. 29 */ 30 31 #include "zen_umc_test.h" 32 33 static const zen_umc_t zen_umc_multi = { 34 .umc_tom = 0x90000000, 35 .umc_tom2 = 0x2470000000, 36 .umc_df_rev = DF_REV_3, 37 .umc_decomp = { 38 .dfd_sock_mask = 0x01, 39 .dfd_die_mask = 0x00, 40 .dfd_node_mask = 0x20, 41 .dfd_comp_mask = 0x1f, 42 .dfd_sock_shift = 0, 43 .dfd_die_shift = 0, 44 .dfd_node_shift = 5, 45 .dfd_comp_shift = 0 46 }, 47 .umc_ndfs = 1, 48 .umc_dfs = { { 49 .zud_flags = ZEN_UMC_DF_F_HOLE_VALID, 50 .zud_dfno = 0, 51 .zud_dram_nrules = 2, 52 .zud_nchan = 4, 53 .zud_cs_nremap = 0, 54 .zud_hole_base = 0x90000000, 55 .zud_rules = { { 56 .ddr_flags = DF_DRAM_F_VALID | DF_DRAM_F_HOLE, 57 .ddr_base = 0, 58 .ddr_limit = 0x1c70000000, 59 .ddr_dest_fabid = 0, 60 .ddr_sock_ileave_bits = 0, 61 .ddr_die_ileave_bits = 0, 62 .ddr_addr_start = 8, 63 .ddr_chan_ileave = DF_CHAN_ILEAVE_1CH 64 }, { 65 .ddr_flags = DF_DRAM_F_VALID, 66 .ddr_base = 0x1c70000000, 67 .ddr_limit = 0x2470000000, 68 .ddr_dest_fabid = 0, 69 .ddr_sock_ileave_bits = 0, 70 .ddr_die_ileave_bits = 0, 71 .ddr_addr_start = 8, 72 .ddr_chan_ileave = DF_CHAN_ILEAVE_2CH 73 } }, 74 .zud_chan = { { 75 .chan_flags = UMC_CHAN_F_ECC_EN, 76 .chan_fabid = 0, 77 .chan_instid = 0, 78 .chan_logid = 0, 79 .chan_nrules = 2, 80 .chan_type = UMC_DIMM_T_DDR4, 81 .chan_rules = { { 82 .ddr_flags = DF_DRAM_F_VALID | DF_DRAM_F_HOLE, 83 .ddr_base = 0, 84 .ddr_limit = 0x1c70000000, 85 .ddr_dest_fabid = 0, 86 .ddr_sock_ileave_bits = 0, 87 .ddr_die_ileave_bits = 0, 88 .ddr_addr_start = 8, 89 .ddr_chan_ileave = DF_CHAN_ILEAVE_1CH 90 }, { 91 .ddr_flags = DF_DRAM_F_VALID, 92 .ddr_base = 0x1c70000000, 93 .ddr_limit = 0x2470000000, 94 .ddr_dest_fabid = 0, 95 .ddr_sock_ileave_bits = 0, 96 .ddr_die_ileave_bits = 0, 97 .ddr_addr_start = 8, 98 .ddr_chan_ileave = DF_CHAN_ILEAVE_2CH 99 } }, 100 .chan_offsets = { { 101 .cho_valid = B_TRUE, 102 .cho_offset = 0x1c00000000, 103 } }, 104 .chan_dimms = { { 105 .ud_flags = UMC_DIMM_F_VALID, 106 .ud_width = UMC_DIMM_W_X4, 107 .ud_kind = UMC_DIMM_K_RDIMM, 108 .ud_dimmno = 0, 109 .ud_cs = { { 110 .ucs_flags = UMC_CS_F_DECODE_EN, 111 .ucs_base = { 112 .udb_base = 0, 113 .udb_valid = B_TRUE 114 }, 115 .ucs_base_mask = 0x7ffffffff, 116 .ucs_nbanks = 0x4, 117 .ucs_ncol = 0xa, 118 .ucs_nrow_lo = 0x12, 119 .ucs_nbank_groups = 0x2, 120 .ucs_row_hi_bit = 0x18, 121 .ucs_row_low_bit = 0x11, 122 .ucs_bank_bits = { 0xf, 0x10, 0xd, 123 0xe }, 124 .ucs_col_bits = { 0x3, 0x4, 0x5, 0x6, 125 0x7, 0x8, 0x9, 0xa, 0xb, 0xc } 126 }, { 127 .ucs_flags = UMC_CS_F_DECODE_EN, 128 .ucs_base = { 129 .udb_base = 0x800000000, 130 .udb_valid = B_TRUE 131 }, 132 .ucs_base_mask = 0x7ffffffff, 133 .ucs_nbanks = 0x4, 134 .ucs_ncol = 0xa, 135 .ucs_nrow_lo = 0x12, 136 .ucs_nbank_groups = 0x2, 137 .ucs_row_hi_bit = 0x18, 138 .ucs_row_low_bit = 0x11, 139 .ucs_bank_bits = { 0xf, 0x10, 0xd, 140 0xe }, 141 .ucs_col_bits = { 0x3, 0x4, 0x5, 0x6, 142 0x7, 0x8, 0x9, 0xa, 0xb, 0xc } 143 } } 144 }, { 145 .ud_flags = UMC_DIMM_F_VALID, 146 .ud_width = UMC_DIMM_W_X4, 147 .ud_kind = UMC_DIMM_K_RDIMM, 148 .ud_dimmno = 1, 149 .ud_cs = { { 150 .ucs_flags = UMC_CS_F_DECODE_EN, 151 .ucs_base = { 152 .udb_base = 0x1000000000, 153 .udb_valid = B_TRUE 154 }, 155 .ucs_base_mask = 0x7ffffffff, 156 .ucs_nbanks = 0x4, 157 .ucs_ncol = 0xa, 158 .ucs_nrow_lo = 0x12, 159 .ucs_nbank_groups = 0x2, 160 .ucs_row_hi_bit = 0x18, 161 .ucs_row_low_bit = 0x11, 162 .ucs_bank_bits = { 0xf, 0x10, 0xd, 163 0xe }, 164 .ucs_col_bits = { 0x3, 0x4, 0x5, 0x6, 165 0x7, 0x8, 0x9, 0xa, 0xb, 0xc } 166 }, { 167 .ucs_flags = UMC_CS_F_DECODE_EN, 168 .ucs_base = { 169 .udb_base = 0x1800000000, 170 .udb_valid = B_TRUE 171 }, 172 .ucs_base_mask = 0x7ffffffff, 173 .ucs_nbanks = 0x4, 174 .ucs_ncol = 0xa, 175 .ucs_nrow_lo = 0x12, 176 .ucs_nbank_groups = 0x2, 177 .ucs_row_hi_bit = 0x18, 178 .ucs_row_low_bit = 0x11, 179 .ucs_bank_bits = { 0xf, 0x10, 0xd, 180 0xe }, 181 .ucs_col_bits = { 0x3, 0x4, 0x5, 0x6, 182 0x7, 0x8, 0x9, 0xa, 0xb, 0xc } 183 } } 184 } } 185 }, { 186 .chan_flags = UMC_CHAN_F_ECC_EN, 187 .chan_fabid = 1, 188 .chan_instid = 1, 189 .chan_logid = 1, 190 .chan_nrules = 1, 191 .chan_type = UMC_DIMM_T_DDR4, 192 .chan_rules = { { 193 .ddr_flags = DF_DRAM_F_VALID, 194 .ddr_base = 0x1c70000000, 195 .ddr_limit = 0x2470000000, 196 .ddr_dest_fabid = 0, 197 .ddr_sock_ileave_bits = 0, 198 .ddr_die_ileave_bits = 0, 199 .ddr_addr_start = 8, 200 .ddr_chan_ileave = DF_CHAN_ILEAVE_2CH 201 } }, 202 .chan_dimms = { { 203 .ud_flags = UMC_DIMM_F_VALID, 204 .ud_width = UMC_DIMM_W_X8, 205 .ud_kind = UMC_DIMM_K_RDIMM, 206 .ud_dimmno = 0, 207 .ud_cs = { { 208 .ucs_flags = UMC_CS_F_DECODE_EN, 209 .ucs_base = { 210 .udb_base = 0, 211 .udb_valid = B_TRUE 212 }, 213 .ucs_base_mask = 0x3fffdffff, 214 .ucs_nbanks = 0x4, 215 .ucs_ncol = 0xa, 216 .ucs_nrow_lo = 0x10, 217 .ucs_nbank_groups = 0x2, 218 .ucs_row_hi_bit = 0x18, 219 .ucs_row_low_bit = 0x11, 220 .ucs_bank_bits = { 0xf, 0x10, 0xd, 221 0xe }, 222 .ucs_col_bits = { 0x3, 0x4, 0x5, 0x6, 223 0x7, 0x8, 0x9, 0xa, 0xb, 0xc } 224 } } 225 }, { 226 .ud_flags = UMC_DIMM_F_VALID, 227 .ud_width = UMC_DIMM_W_X8, 228 .ud_kind = UMC_DIMM_K_RDIMM, 229 .ud_dimmno = 0, 230 .ud_cs = { { 231 .ucs_flags = UMC_CS_F_DECODE_EN, 232 .ucs_base = { 233 .udb_base = 0x20000, 234 .udb_valid = B_TRUE 235 }, 236 .ucs_base_mask = 0x3fffdffff, 237 .ucs_nbanks = 0x4, 238 .ucs_ncol = 0xa, 239 .ucs_nrow_lo = 0x10, 240 .ucs_nbank_groups = 0x2, 241 .ucs_row_hi_bit = 0x18, 242 .ucs_row_low_bit = 0x11, 243 .ucs_bank_bits = { 0xf, 0x10, 0xd, 244 0xe }, 245 .ucs_col_bits = { 0x3, 0x4, 0x5, 0x6, 246 0x7, 0x8, 0x9, 0xa, 0xb, 0xc } 247 } } 248 } }, 249 } } 250 } } 251 }; 252 253 const umc_decode_test_t zen_umc_test_multi[] = { { 254 .udt_desc = "Multi-rule (0)", 255 .udt_umc = &zen_umc_multi, 256 .udt_pa = 0x12345603, 257 .udt_pass = B_TRUE, 258 .udt_norm_addr = 0x12345603, 259 .udt_sock = 0, 260 .udt_die = 0, 261 .udt_comp = 0, 262 .udt_dimm_no = 0, 263 .udt_dimm_col = 0x2c0, 264 .udt_dimm_row = 0x91a, 265 .udt_dimm_bank = 2, 266 .udt_dimm_bank_group = 0, 267 .udt_dimm_subchan = UINT8_MAX, 268 .udt_dimm_rm = 0, 269 .udt_dimm_cs = 0 270 271 }, { 272 .udt_desc = "Multi-rule (1)", 273 .udt_umc = &zen_umc_multi, 274 .udt_pa = 0x12345703, 275 .udt_pass = B_TRUE, 276 .udt_norm_addr = 0x12345703, 277 .udt_sock = 0, 278 .udt_die = 0, 279 .udt_comp = 0, 280 .udt_dimm_no = 0, 281 .udt_dimm_col = 0x2e0, 282 .udt_dimm_row = 0x91a, 283 .udt_dimm_bank = 2, 284 .udt_dimm_bank_group = 0, 285 .udt_dimm_subchan = UINT8_MAX, 286 .udt_dimm_rm = 0, 287 .udt_dimm_cs = 0 288 289 }, { 290 .udt_desc = "Multi-rule (2)", 291 .udt_umc = &zen_umc_multi, 292 .udt_pa = 0x1ba9876543, 293 .udt_pass = B_TRUE, 294 .udt_norm_addr = 0x1b39876543, 295 .udt_sock = 0, 296 .udt_die = 0, 297 .udt_comp = 0, 298 .udt_dimm_no = 1, 299 .udt_dimm_col = 0xa8, 300 .udt_dimm_row = 0x19cc3, 301 .udt_dimm_bank = 3, 302 .udt_dimm_bank_group = 2, 303 .udt_dimm_subchan = UINT8_MAX, 304 .udt_dimm_rm = 0, 305 .udt_dimm_cs = 1 306 307 }, { 308 .udt_desc = "Multi-rule (3)", 309 .udt_umc = &zen_umc_multi, 310 .udt_pa = 0x1ba9876643, 311 .udt_pass = B_TRUE, 312 .udt_norm_addr = 0x1b39876643, 313 .udt_sock = 0, 314 .udt_die = 0, 315 .udt_comp = 0, 316 .udt_dimm_no = 1, 317 .udt_dimm_col = 0xc8, 318 .udt_dimm_row = 0x19cc3, 319 .udt_dimm_bank = 3, 320 .udt_dimm_bank_group = 2, 321 .udt_dimm_subchan = UINT8_MAX, 322 .udt_dimm_rm = 0, 323 .udt_dimm_cs = 1 324 }, 325 /* 326 * All of the accesses below should now hit our second rule. When normalizing we 327 * subtract the base and add the channel offset. So that is why the normalized 328 * address will look totally different depending on which DIMM we go to. 329 */ 330 { 331 .udt_desc = "Multi-rule (4)", 332 .udt_umc = &zen_umc_multi, 333 .udt_pa = 0x1c70000000, 334 .udt_pass = B_TRUE, 335 .udt_norm_addr = 0x1c00000000, 336 .udt_sock = 0, 337 .udt_die = 0, 338 .udt_comp = 0, 339 .udt_dimm_no = 1, 340 .udt_dimm_col = 0, 341 .udt_dimm_row = 0x20000, 342 .udt_dimm_bank = 0, 343 .udt_dimm_bank_group = 0, 344 .udt_dimm_subchan = UINT8_MAX, 345 .udt_dimm_rm = 0, 346 .udt_dimm_cs = 1 347 }, { 348 .udt_desc = "Multi-rule (5)", 349 .udt_umc = &zen_umc_multi, 350 .udt_pa = 0x1c70000100, 351 .udt_pass = B_TRUE, 352 .udt_norm_addr = 0x0, 353 .udt_sock = 0, 354 .udt_die = 0, 355 .udt_comp = 1, 356 .udt_dimm_no = 0, 357 .udt_dimm_col = 0, 358 .udt_dimm_row = 0, 359 .udt_dimm_bank = 0, 360 .udt_dimm_bank_group = 0, 361 .udt_dimm_subchan = UINT8_MAX, 362 .udt_dimm_rm = 0, 363 .udt_dimm_cs = 0 364 }, { 365 .udt_desc = "Multi-rule (6)", 366 .udt_umc = &zen_umc_multi, 367 .udt_pa = 0x23456789ab, 368 .udt_pass = B_TRUE, 369 .udt_norm_addr = 0x36ab3c4ab, 370 .udt_sock = 0, 371 .udt_die = 0, 372 .udt_comp = 1, 373 .udt_dimm_no = 1, 374 .udt_dimm_col = 0x95, 375 .udt_dimm_row = 0xb559, 376 .udt_dimm_bank = 2, 377 .udt_dimm_bank_group = 3, 378 .udt_dimm_subchan = UINT8_MAX, 379 .udt_dimm_rm = 0, 380 .udt_dimm_cs = 0 381 }, { 382 .udt_desc = "Multi-rule (7)", 383 .udt_umc = &zen_umc_multi, 384 .udt_pa = 0x2345678aab, 385 .udt_pass = B_TRUE, 386 .udt_norm_addr = 0x1f6ab3c5ab, 387 .udt_sock = 0, 388 .udt_die = 0, 389 .udt_comp = 0, 390 .udt_dimm_no = 1, 391 .udt_dimm_col = 0xb5, 392 .udt_dimm_row = 0x3b559, 393 .udt_dimm_bank = 2, 394 .udt_dimm_bank_group = 3, 395 .udt_dimm_subchan = UINT8_MAX, 396 .udt_dimm_rm = 0, 397 .udt_dimm_cs = 1 398 }, { 399 .udt_desc = NULL 400 } }; 401