master
c 642 lines 23.9 KB
Raw
1 /*
2 * CXL Utility library for components
3 *
4 * Copyright(C) 2020 Intel Corporation.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2. See the
7 * COPYING file in the top-level directory.
8 */
9
10 #include "qemu/osdep.h"
11 #include "qemu/log.h"
12 #include "qapi/error.h"
13 #include "hw/pci/pci.h"
14 #include "hw/cxl/cxl.h"
15
16 /* CXL r3.1 Section 8.2.4.20.1 CXL HDM Decoder Capability Register */
17 int cxl_decoder_count_enc(int count)
18 {
19 switch (count) {
20 case 1: return 0x0;
21 case 2: return 0x1;
22 case 4: return 0x2;
23 case 6: return 0x3;
24 case 8: return 0x4;
25 case 10: return 0x5;
26 /* Switches and Host Bridges may have more than 10 decoders */
27 case 12: return 0x6;
28 case 14: return 0x7;
29 case 16: return 0x8;
30 case 20: return 0x9;
31 case 24: return 0xa;
32 case 28: return 0xb;
33 case 32: return 0xc;
34 }
35 return 0;
36 }
37
38 int cxl_decoder_count_dec(int enc_cnt)
39 {
40 switch (enc_cnt) {
41 case 0x0: return 1;
42 case 0x1: return 2;
43 case 0x2: return 4;
44 case 0x3: return 6;
45 case 0x4: return 8;
46 case 0x5: return 10;
47 /* Switches and Host Bridges may have more than 10 decoders */
48 case 0x6: return 12;
49 case 0x7: return 14;
50 case 0x8: return 16;
51 case 0x9: return 20;
52 case 0xa: return 24;
53 case 0xb: return 28;
54 case 0xc: return 32;
55 }
56 return 0;
57 }
58
59 hwaddr cxl_decode_ig(int ig)
60 {
61 return 1ULL << (ig + 8);
62 }
63
64 static uint64_t cxl_cache_mem_read_reg(void *opaque, hwaddr offset,
65 unsigned size)
66 {
67 CXLComponentState *cxl_cstate = opaque;
68 ComponentRegisters *cregs = &cxl_cstate->crb;
69
70 switch (size) {
71 case 4: {
72 QEMU_BUILD_BUG_ON(sizeof(*cregs->cache_mem_registers) != 4);
73
74 if (offset == A_CXL_BI_RT_STATUS ||
75 offset == A_CXL_BI_DECODER_STATUS) {
76 int type;
77 uint64_t started;
78
79 type = (offset == A_CXL_BI_RT_STATUS) ?
80 CXL_BISTATE_RT : CXL_BISTATE_DECODER;
81 started = cxl_cstate->bi_state[type].last_commit;
82
83 if (started) {
84 uint32_t *cache_mem = cregs->cache_mem_registers;
85 uint32_t val = cache_mem[offset / 4];
86 uint64_t now;
87 int set;
88
89 now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
90 /* arbitrary 100 ms to do the commit */
91 set = !!(now >= started + 100);
92
93 if (offset == A_CXL_BI_RT_STATUS) {
94 val = FIELD_DP32(val, CXL_BI_RT_STATUS, COMMITTED, set);
95 } else {
96 val = FIELD_DP32(val, CXL_BI_DECODER_STATUS, COMMITTED,
97 set);
98 }
99 stl_le_p((uint8_t *)cache_mem + offset, val);
100 }
101 }
102
103 return cregs->cache_mem_registers[offset / 4];
104 }
105 case 8:
106 qemu_log_mask(LOG_UNIMP,
107 "CXL 8 byte cache mem registers not implemented\n");
108 return 0;
109 default:
110 /*
111 * In line with specification limitaions on access sizes, this
112 * routine is not called with other sizes.
113 */
114 g_assert_not_reached();
115 }
116 }
117
118 static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset,
119 uint32_t value)
120 {
121 ComponentRegisters *cregs = &cxl_cstate->crb;
122 uint32_t *cache_mem = cregs->cache_mem_registers;
123 bool should_commit = false;
124 bool should_uncommit = false;
125
126 switch (offset) {
127 case A_CXL_HDM_DECODER0_CTRL:
128 case A_CXL_HDM_DECODER1_CTRL:
129 case A_CXL_HDM_DECODER2_CTRL:
130 case A_CXL_HDM_DECODER3_CTRL:
131 should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
132 should_uncommit = !should_commit;
133 break;
134 default:
135 break;
136 }
137
138 if (should_commit) {
139 value = FIELD_DP32(value, CXL_HDM_DECODER0_CTRL, ERR, 0);
140 value = FIELD_DP32(value, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
141 } else if (should_uncommit) {
142 value = FIELD_DP32(value, CXL_HDM_DECODER0_CTRL, ERR, 0);
143 value = FIELD_DP32(value, CXL_HDM_DECODER0_CTRL, COMMITTED, 0);
144 }
145 stl_le_p((uint8_t *)cache_mem + offset, value);
146
147 if (should_commit) {
148 cfmws_update_non_interleaved(true);
149 } else if (should_uncommit) {
150 cfmws_update_non_interleaved(false);
151 }
152 }
153
154 static void bi_handler(CXLComponentState *cxl_cstate, hwaddr offset,
155 uint32_t value)
156 {
157 ComponentRegisters *cregs = &cxl_cstate->crb;
158 uint32_t sts, *cache_mem = cregs->cache_mem_registers;
159 bool to_commit = false;
160 int type = 0; /* Unused value - work around for compiler warning */
161
162 switch (offset) {
163 case A_CXL_BI_RT_CTRL:
164 to_commit = FIELD_EX32(value, CXL_BI_RT_CTRL, COMMIT);
165 if (to_commit) {
166 sts = cxl_cache_mem_read_reg(cxl_cstate,
167 R_CXL_BI_RT_STATUS, 4);
168 sts = FIELD_DP32(sts, CXL_BI_RT_STATUS, COMMITTED, 0);
169 stl_le_p((uint8_t *)cache_mem + R_CXL_BI_RT_STATUS, sts);
170 type = CXL_BISTATE_RT;
171 }
172 break;
173 case A_CXL_BI_DECODER_CTRL:
174 to_commit = FIELD_EX32(value, CXL_BI_DECODER_CTRL, COMMIT);
175 if (to_commit) {
176 sts = cxl_cache_mem_read_reg(cxl_cstate,
177 R_CXL_BI_DECODER_STATUS, 4);
178 sts = FIELD_DP32(sts, CXL_BI_DECODER_STATUS, COMMITTED, 0);
179 stl_le_p((uint8_t *)cache_mem + R_CXL_BI_DECODER_STATUS, sts);
180 type = CXL_BISTATE_DECODER;
181 }
182 break;
183 default:
184 break;
185 }
186
187 if (to_commit) {
188 cxl_cstate->bi_state[type].last_commit =
189 qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
190 }
191
192 stl_le_p((uint8_t *)cache_mem + offset, value);
193 }
194
195 static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
196 unsigned size)
197 {
198 CXLComponentState *cxl_cstate = opaque;
199 ComponentRegisters *cregs = &cxl_cstate->crb;
200 uint32_t mask;
201
202 switch (size) {
203 case 4: {
204 QEMU_BUILD_BUG_ON(sizeof(*cregs->cache_mem_regs_write_mask) != 4);
205 QEMU_BUILD_BUG_ON(sizeof(*cregs->cache_mem_registers) != 4);
206 mask = cregs->cache_mem_regs_write_mask[offset / 4];
207 value &= mask;
208 /* RO bits should remain constant. Done by reading existing value */
209 value |= ~mask & cregs->cache_mem_registers[offset / 4];
210 if (cregs->special_ops && cregs->special_ops->write) {
211 cregs->special_ops->write(cxl_cstate, offset, value, size);
212 return;
213 }
214
215 if (offset >= A_CXL_HDM_DECODER_CAPABILITY &&
216 offset <= A_CXL_HDM_DECODER3_TARGET_LIST_HI) {
217 dumb_hdm_handler(cxl_cstate, offset, value);
218 } else if (offset == A_CXL_BI_RT_CTRL ||
219 offset == A_CXL_BI_DECODER_CTRL) {
220 bi_handler(cxl_cstate, offset, value);
221 } else {
222 cregs->cache_mem_registers[offset / 4] = value;
223 }
224 return;
225 }
226 case 8:
227 qemu_log_mask(LOG_UNIMP,
228 "CXL 8 byte cache mem registers not implemented\n");
229 return;
230 default:
231 /*
232 * In line with specification limitaions on access sizes, this
233 * routine is not called with other sizes.
234 */
235 g_assert_not_reached();
236 }
237 }
238
239 /*
240 * CXL r3.1 Section 8.2.3: Component Register Layout and Definition
241 * The access restrictions specified in Section 8.2.2 also apply to CXL 2.0
242 * Component Registers.
243 *
244 * CXL r3.1 Section 8.2.2: Accessing Component Registers
245 * • A 32 bit register shall be accessed as a 4 Bytes quantity. Partial
246 * reads are not permitted.
247 * • A 64 bit register shall be accessed as a 8 Bytes quantity. Partial
248 * reads are not permitted.
249 *
250 * As of the spec defined today, only 4 byte registers exist.
251 */
252 static const MemoryRegionOps cache_mem_ops = {
253 .read = cxl_cache_mem_read_reg,
254 .write = cxl_cache_mem_write_reg,
255 .endianness = DEVICE_LITTLE_ENDIAN,
256 .valid = {
257 .min_access_size = 4,
258 .max_access_size = 8,
259 .unaligned = false,
260 },
261 .impl = {
262 .min_access_size = 4,
263 .max_access_size = 8,
264 },
265 };
266
267 void cxl_component_register_block_init(Object *obj,
268 CXLComponentState *cxl_cstate,
269 const char *type)
270 {
271 ComponentRegisters *cregs = &cxl_cstate->crb;
272
273 memory_region_init(&cregs->component_registers, obj, type,
274 CXL2_COMPONENT_BLOCK_SIZE);
275
276 /* io registers controls link which we don't care about in QEMU */
277 memory_region_init_io(&cregs->io, obj, NULL, NULL, ".io",
278 CXL2_COMPONENT_IO_REGION_SIZE);
279 memory_region_init_io(&cregs->cache_mem, obj, &cache_mem_ops, cxl_cstate,
280 ".cache_mem", CXL2_COMPONENT_CM_REGION_SIZE);
281
282 memory_region_add_subregion(&cregs->component_registers, 0, &cregs->io);
283 memory_region_add_subregion(&cregs->component_registers,
284 CXL2_COMPONENT_IO_REGION_SIZE,
285 &cregs->cache_mem);
286 }
287
288 static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
289 {
290 /*
291 * Error status is RW1C but given bits are not yet set, it can
292 * be handled as RO.
293 */
294 stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_STATUS, 0);
295 stl_le_p(write_msk + R_CXL_RAS_UNC_ERR_STATUS, 0x1cfff);
296 /* Bits 12-13 and 17-31 reserved in CXL 2.0 */
297 stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_MASK, 0x1cfff);
298 stl_le_p(write_msk + R_CXL_RAS_UNC_ERR_MASK, 0x1cfff);
299 stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_SEVERITY, 0x1cfff);
300 stl_le_p(write_msk + R_CXL_RAS_UNC_ERR_SEVERITY, 0x1cfff);
301 stl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS, 0);
302 stl_le_p(write_msk + R_CXL_RAS_COR_ERR_STATUS, 0x7f);
303 stl_le_p(reg_state + R_CXL_RAS_COR_ERR_MASK, 0x7f);
304 stl_le_p(write_msk + R_CXL_RAS_COR_ERR_MASK, 0x7f);
305 /* CXL switches and devices must set */
306 stl_le_p(reg_state + R_CXL_RAS_ERR_CAP_CTRL, 0x200);
307 }
308
309 static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
310 enum reg_type type, bool bi)
311 {
312 int decoder_count = CXL_HDM_DECODER_COUNT;
313 int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
314 int i;
315
316 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT,
317 cxl_decoder_count_enc(decoder_count));
318 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT, 1);
319 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_256B, 1);
320 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_4K, 1);
321 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
322 POISON_ON_ERR_CAP, 0);
323 if (type == CXL2_TYPE3_DEVICE) {
324 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 1);
325 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 1);
326 } else {
327 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
328 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
329 }
330 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO, 0);
331 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
332 UIO_DECODER_COUNT, 0);
333 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, MEMDATA_NXM_CAP, 0);
334 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
335 SUPPORTED_COHERENCY_MODEL,
336 /* host+dev or Unknown */
337 type == CXL2_TYPE3_DEVICE && bi ? 3 : 0);
338 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_GLOBAL_CONTROL,
339 HDM_DECODER_ENABLE, 0);
340 write_msk[R_CXL_HDM_DECODER_GLOBAL_CONTROL] = 0x3;
341 for (i = 0; i < decoder_count; i++) {
342 write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc] = 0xf0000000;
343 write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc] = 0xffffffff;
344 write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc] = 0xf0000000;
345 write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc] = 0xffffffff;
346 write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] = 0x13ff;
347 if (type == CXL2_DEVICE ||
348 type == CXL2_TYPE3_DEVICE ||
349 type == CXL2_LOGICAL_DEVICE) {
350 write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * hdm_inc] =
351 0xf0000000;
352 } else {
353 write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * hdm_inc] =
354 0xffffffff;
355 }
356 write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * hdm_inc] = 0xffffffff;
357 }
358 }
359
360 static void bi_rt_init_common(uint32_t *reg_state, uint32_t *write_msk)
361 {
362 /* switch usp must commit the new BI-ID, timeout of 2secs */
363 ARRAY_FIELD_DP32(reg_state, CXL_BI_RT_CAPABILITY, EXPLICIT_COMMIT, 1);
364
365 ARRAY_FIELD_DP32(reg_state, CXL_BI_RT_CTRL, COMMIT, 0);
366 write_msk[R_CXL_BI_RT_CTRL] = 0x1;
367
368 ARRAY_FIELD_DP32(reg_state, CXL_BI_RT_STATUS, COMMITTED, 0);
369 ARRAY_FIELD_DP32(reg_state, CXL_BI_RT_STATUS, ERR_NOT_COMMITTED, 0);
370 ARRAY_FIELD_DP32(reg_state, CXL_BI_RT_STATUS, COMMIT_TMO_SCALE, 0x6);
371 ARRAY_FIELD_DP32(reg_state, CXL_BI_RT_STATUS, COMMIT_TMO_BASE, 0x2);
372 }
373
374 static void bi_decoder_init_common(uint32_t *reg_state, uint32_t *write_msk,
375 enum reg_type type)
376 {
377 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_CAPABILITY, HDM_D, 0);
378 /* switch dsp must commit the new BI-ID, timeout of 2secs */
379 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_CAPABILITY, EXPLICIT_COMMIT,
380 (type != CXL2_ROOT_PORT && type != CXL2_TYPE3_DEVICE));
381
382 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_CTRL, BI_FW, 0);
383 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_CTRL, BI_ENABLE, 0);
384 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_CTRL, COMMIT, 0);
385 write_msk[R_CXL_BI_DECODER_CTRL] = 0x7;
386
387 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_STATUS, COMMITTED, 0);
388 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_STATUS, ERR_NOT_COMMITTED, 0);
389 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_STATUS, COMMIT_TMO_SCALE, 0x6);
390 ARRAY_FIELD_DP32(reg_state, CXL_BI_DECODER_STATUS, COMMIT_TMO_BASE, 0x2);
391 }
392
393 void cxl_component_register_init_common(uint32_t *reg_state,
394 uint32_t *write_msk,
395 enum reg_type type,
396 bool bi)
397 {
398 int caps = 0;
399
400 memset(reg_state, 0, CXL2_COMPONENT_CM_REGION_SIZE);
401
402 /* CXL Capability Header Register */
403 ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, ID, 1);
404 ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, VERSION,
405 CXL_CAPABILITY_VERSION);
406 ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, CACHE_MEM_VERSION, 1);
407
408 #define init_cap_reg(reg, id, version) \
409 do { \
410 int which = CXL_##reg##_CAP_HDR_IDX; \
411 if (CXL_##reg##_CAP_HDR_IDX > caps) \
412 caps = CXL_##reg##_CAP_HDR_IDX; \
413 reg_state[which] = FIELD_DP32(reg_state[which], \
414 CXL_##reg##_CAPABILITY_HEADER, ID, id); \
415 reg_state[which] = \
416 FIELD_DP32(reg_state[which], CXL_##reg##_CAPABILITY_HEADER, \
417 VERSION, version); \
418 reg_state[which] = \
419 FIELD_DP32(reg_state[which], CXL_##reg##_CAPABILITY_HEADER, PTR, \
420 CXL_##reg##_REGISTERS_OFFSET); \
421 } while (0)
422
423 /* CXL r3.2 8.2.4 Table 8-22 */
424 switch (type) {
425 case CXL2_ROOT_PORT:
426 case CXL2_RC:
427 /* + Extended Security, + Snoop */
428 init_cap_reg(EXTSEC, 6, 1);
429 init_cap_reg(SNOOP, 8, 1);
430 /* fallthrough */
431 case CXL2_UPSTREAM_PORT:
432 case CXL2_TYPE3_DEVICE:
433 case CXL2_LOGICAL_DEVICE:
434 /* + HDM */
435 init_cap_reg(HDM, 5, 1);
436 hdm_init_common(reg_state, write_msk, type, bi);
437 /* fallthrough */
438 case CXL2_DOWNSTREAM_PORT:
439 case CXL2_DEVICE:
440 /* RAS, Link */
441 if (type != CXL2_RC) {
442 init_cap_reg(RAS, 2, 2);
443 ras_init_common(reg_state, write_msk);
444 }
445 init_cap_reg(LINK, 4, 2);
446 break;
447 default:
448 abort();
449 }
450
451 /* back invalidate */
452 if (bi) {
453 switch (type) {
454 case CXL2_UPSTREAM_PORT:
455 init_cap_reg(BI_RT, 11, CXL_BI_RT_CAP_VERSION);
456 bi_rt_init_common(reg_state, write_msk);
457 break;
458 case CXL2_ROOT_PORT:
459 case CXL2_DOWNSTREAM_PORT:
460 case CXL2_TYPE3_DEVICE:
461 init_cap_reg(BI_DECODER, 12, CXL_BI_DECODER_CAP_VERSION);
462 bi_decoder_init_common(reg_state, write_msk, type);
463 break;
464 default:
465 break;
466 }
467 }
468
469 ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, ARRAY_SIZE, caps);
470 #undef init_cap_reg
471 }
472
473 /*
474 * Helper to creates a DVSEC header for a CXL entity. The caller is responsible
475 * for tracking the valid offset.
476 *
477 * This function will build the DVSEC header on behalf of the caller and then
478 * copy in the remaining data for the vendor specific bits.
479 * It will also set up appropriate write masks.
480 */
481 void cxl_component_create_dvsec(CXLComponentState *cxl,
482 enum reg_type cxl_dev_type, uint16_t length,
483 uint16_t type, uint8_t rev, uint8_t *body)
484 {
485 PCIDevice *pdev = cxl->pdev;
486 uint16_t offset = cxl->dvsec_offset;
487 uint8_t *wmask = pdev->wmask;
488
489 assert(offset >= PCI_CFG_SPACE_SIZE &&
490 ((offset + length) < PCI_CFG_SPACE_EXP_SIZE));
491 assert((length & 0xf000) == 0);
492 assert((rev & ~0xf) == 0);
493
494 /* Create the DVSEC in the MCFG space */
495 pcie_add_capability(pdev, PCI_EXT_CAP_ID_DVSEC, 1, offset, length);
496 pci_set_long(pdev->config + offset + PCIE_DVSEC_HEADER1_OFFSET,
497 (length << 20) | (rev << 16) | CXL_VENDOR_ID);
498 pci_set_word(pdev->config + offset + PCIE_DVSEC_ID_OFFSET, type);
499 memcpy(pdev->config + offset + sizeof(DVSECHeader),
500 body + sizeof(DVSECHeader),
501 length - sizeof(DVSECHeader));
502
503 /* Configure write masks */
504 switch (type) {
505 case PCIE_CXL_DEVICE_DVSEC:
506 /* Cntrl RW Lock - so needs explicit blocking when lock is set */
507 wmask[offset + offsetof(CXLDVSECDevice, ctrl)] = 0xFD;
508 wmask[offset + offsetof(CXLDVSECDevice, ctrl) + 1] = 0x4F;
509 /* Status is RW1CS */
510 wmask[offset + offsetof(CXLDVSECDevice, ctrl2)] = 0x0F;
511 /* Lock is RW Once */
512 wmask[offset + offsetof(CXLDVSECDevice, lock)] = 0x01;
513 /* range1/2_base_high/low is RW Lock */
514 wmask[offset + offsetof(CXLDVSECDevice, range1_base_hi)] = 0xFF;
515 wmask[offset + offsetof(CXLDVSECDevice, range1_base_hi) + 1] = 0xFF;
516 wmask[offset + offsetof(CXLDVSECDevice, range1_base_hi) + 2] = 0xFF;
517 wmask[offset + offsetof(CXLDVSECDevice, range1_base_hi) + 3] = 0xFF;
518 wmask[offset + offsetof(CXLDVSECDevice, range1_base_lo) + 3] = 0xF0;
519 wmask[offset + offsetof(CXLDVSECDevice, range2_base_hi)] = 0xFF;
520 wmask[offset + offsetof(CXLDVSECDevice, range2_base_hi) + 1] = 0xFF;
521 wmask[offset + offsetof(CXLDVSECDevice, range2_base_hi) + 2] = 0xFF;
522 wmask[offset + offsetof(CXLDVSECDevice, range2_base_hi) + 3] = 0xFF;
523 wmask[offset + offsetof(CXLDVSECDevice, range2_base_lo) + 3] = 0xF0;
524 break;
525 case NON_CXL_FUNCTION_MAP_DVSEC:
526 break; /* Not yet implemented */
527 case EXTENSIONS_PORT_DVSEC:
528 wmask[offset + offsetof(CXLDVSECPortExt, control)] = 0x0F;
529 wmask[offset + offsetof(CXLDVSECPortExt, control) + 1] = 0x40;
530 wmask[offset + offsetof(CXLDVSECPortExt, alt_bus_base)] = 0xFF;
531 wmask[offset + offsetof(CXLDVSECPortExt, alt_bus_limit)] = 0xFF;
532 wmask[offset + offsetof(CXLDVSECPortExt, alt_memory_base)] = 0xF0;
533 wmask[offset + offsetof(CXLDVSECPortExt, alt_memory_base) + 1] = 0xFF;
534 wmask[offset + offsetof(CXLDVSECPortExt, alt_memory_limit)] = 0xF0;
535 wmask[offset + offsetof(CXLDVSECPortExt, alt_memory_limit) + 1] = 0xFF;
536 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_base)] = 0xF0;
537 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_base) + 1] = 0xFF;
538 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_limit)] = 0xF0;
539 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_limit) + 1] =
540 0xFF;
541 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_base_high)] =
542 0xFF;
543 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_base_high) + 1] =
544 0xFF;
545 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_base_high) + 2] =
546 0xFF;
547 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_base_high) + 3] =
548 0xFF;
549 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_limit_high)] =
550 0xFF;
551 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_limit_high) + 1] =
552 0xFF;
553 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_limit_high) + 2] =
554 0xFF;
555 wmask[offset + offsetof(CXLDVSECPortExt, alt_prefetch_limit_high) + 3] =
556 0xFF;
557 break;
558 case GPF_PORT_DVSEC:
559 wmask[offset + offsetof(CXLDVSECPortGPF, phase1_ctrl)] = 0x0F;
560 wmask[offset + offsetof(CXLDVSECPortGPF, phase1_ctrl) + 1] = 0x0F;
561 wmask[offset + offsetof(CXLDVSECPortGPF, phase2_ctrl)] = 0x0F;
562 wmask[offset + offsetof(CXLDVSECPortGPF, phase2_ctrl) + 1] = 0x0F;
563 break;
564 case GPF_DEVICE_DVSEC:
565 wmask[offset + offsetof(CXLDVSECDeviceGPF, phase2_duration)] = 0x0F;
566 wmask[offset + offsetof(CXLDVSECDeviceGPF, phase2_duration) + 1] = 0x0F;
567 wmask[offset + offsetof(CXLDVSECDeviceGPF, phase2_power)] = 0xFF;
568 wmask[offset + offsetof(CXLDVSECDeviceGPF, phase2_power) + 1] = 0xFF;
569 wmask[offset + offsetof(CXLDVSECDeviceGPF, phase2_power) + 2] = 0xFF;
570 wmask[offset + offsetof(CXLDVSECDeviceGPF, phase2_power) + 3] = 0xFF;
571 break;
572 case PCIE_FLEXBUS_PORT_DVSEC:
573 switch (cxl_dev_type) {
574 case CXL2_ROOT_PORT:
575 /* No MLD */
576 wmask[offset + offsetof(CXLDVSECPortFlexBus, ctrl)] = 0xbd;
577 break;
578 case CXL2_DOWNSTREAM_PORT:
579 wmask[offset + offsetof(CXLDVSECPortFlexBus, ctrl)] = 0xfd;
580 break;
581 default: /* Registers are RO for other component types */
582 break;
583 }
584 /* There are rw1cs bits in the status register but never set */
585 break;
586 }
587
588 /* Update state for future DVSEC additions */
589 range_init_nofail(&cxl->dvsecs[type], cxl->dvsec_offset, length);
590 cxl->dvsec_offset += length;
591 }
592
593 /* CXL r3.1 Section 8.2.4.20.7 CXL HDM Decoder n Control Register */
594 uint8_t cxl_interleave_ways_enc(int iw, Error **errp)
595 {
596 switch (iw) {
597 case 1: return 0x0;
598 case 2: return 0x1;
599 case 4: return 0x2;
600 case 8: return 0x3;
601 case 16: return 0x4;
602 case 3: return 0x8;
603 case 6: return 0x9;
604 case 12: return 0xa;
605 default:
606 error_setg(errp, "Interleave ways: %d not supported", iw);
607 return 0;
608 }
609 }
610
611 int cxl_interleave_ways_dec(uint8_t iw_enc, Error **errp)
612 {
613 switch (iw_enc) {
614 case 0x0: return 1;
615 case 0x1: return 2;
616 case 0x2: return 4;
617 case 0x3: return 8;
618 case 0x4: return 16;
619 case 0x8: return 3;
620 case 0x9: return 6;
621 case 0xa: return 12;
622 default:
623 error_setg(errp, "Encoded interleave ways: %d not supported", iw_enc);
624 return 0;
625 }
626 }
627
628 uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp)
629 {
630 switch (gran) {
631 case 256: return 0;
632 case 512: return 1;
633 case 1024: return 2;
634 case 2048: return 3;
635 case 4096: return 4;
636 case 8192: return 5;
637 case 16384: return 6;
638 default:
639 error_setg(errp, "Interleave granularity: %" PRIu64 " invalid", gran);
640 return 0;
641 }
642 }