master
c 2,499 lines 82.7 KB
Raw
1 /*
2 * CXL Type 3 (memory expander) device
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 * SPDX-License-Identifier: GPL-v2-only
10 */
11 #include "qemu/osdep.h"
12 #include <math.h>
13
14 #include "qemu/units.h"
15 #include "qemu/error-report.h"
16 #include "qapi/qapi-commands-cxl.h"
17 #include "hw/mem/memory-device.h"
18 #include "hw/mem/pc-dimm.h"
19 #include "hw/pci/pci.h"
20 #include "hw/core/qdev-properties.h"
21 #include "hw/core/qdev-properties-system.h"
22 #include "qapi/error.h"
23 #include "qemu/log.h"
24 #include "qemu/module.h"
25 #include "qemu/pmem.h"
26 #include "qemu/range.h"
27 #include "qemu/rcu.h"
28 #include "qemu/guest-random.h"
29 #include "system/hostmem.h"
30 #include "system/numa.h"
31 #include "hw/cxl/cxl.h"
32 #include "hw/pci/msix.h"
33
34 /* type3 device private */
35 enum CXL_T3_MSIX_VECTOR {
36 CXL_T3_MSIX_PCIE_DOE_TABLE_ACCESS = 0,
37 CXL_T3_MSIX_EVENT_START = 2,
38 CXL_T3_MSIX_MBOX = CXL_T3_MSIX_EVENT_START + CXL_EVENT_TYPE_MAX,
39 CXL_T3_MSIX_VECTOR_NR
40 };
41
42 #define DWORD_BYTE 4
43 #define CXL_CAPACITY_MULTIPLIER (256 * MiB)
44
45 /* Default CDAT entries for a memory region */
46 enum {
47 CT3_CDAT_DSMAS,
48 CT3_CDAT_DSLBIS0,
49 CT3_CDAT_DSLBIS1,
50 CT3_CDAT_DSLBIS2,
51 CT3_CDAT_DSLBIS3,
52 CT3_CDAT_DSEMTS,
53 CT3_CDAT_NUM_ENTRIES
54 };
55
56 static void ct3_build_cdat_entries_for_mr(CDATSubHeader **cdat_table,
57 int dsmad_handle, uint64_t size,
58 bool is_pmem, bool is_dynamic,
59 uint64_t dpa_base)
60 {
61 CDATDsmas *dsmas;
62 CDATDslbis *dslbis0;
63 CDATDslbis *dslbis1;
64 CDATDslbis *dslbis2;
65 CDATDslbis *dslbis3;
66 CDATDsemts *dsemts;
67
68 dsmas = g_malloc(sizeof(*dsmas));
69 *dsmas = (CDATDsmas) {
70 .header = {
71 .type = CDAT_TYPE_DSMAS,
72 .length = sizeof(*dsmas),
73 },
74 .DSMADhandle = dsmad_handle,
75 .flags = (is_pmem ? CDAT_DSMAS_FLAG_NV : 0) |
76 (is_dynamic ? CDAT_DSMAS_FLAG_DYNAMIC_CAP : 0),
77 .DPA_base = dpa_base,
78 .DPA_length = size,
79 };
80
81 /* For now, no memory side cache, plausiblish numbers */
82 dslbis0 = g_malloc(sizeof(*dslbis0));
83 *dslbis0 = (CDATDslbis) {
84 .header = {
85 .type = CDAT_TYPE_DSLBIS,
86 .length = sizeof(*dslbis0),
87 },
88 .handle = dsmad_handle,
89 .flags = HMAT_LB_MEM_MEMORY,
90 .data_type = HMAT_LB_DATA_READ_LATENCY,
91 .entry_base_unit = 10000, /* 10ns base */
92 .entry[0] = 15, /* 150ns */
93 };
94
95 dslbis1 = g_malloc(sizeof(*dslbis1));
96 *dslbis1 = (CDATDslbis) {
97 .header = {
98 .type = CDAT_TYPE_DSLBIS,
99 .length = sizeof(*dslbis1),
100 },
101 .handle = dsmad_handle,
102 .flags = HMAT_LB_MEM_MEMORY,
103 .data_type = HMAT_LB_DATA_WRITE_LATENCY,
104 .entry_base_unit = 10000,
105 .entry[0] = 25, /* 250ns */
106 };
107
108 dslbis2 = g_malloc(sizeof(*dslbis2));
109 *dslbis2 = (CDATDslbis) {
110 .header = {
111 .type = CDAT_TYPE_DSLBIS,
112 .length = sizeof(*dslbis2),
113 },
114 .handle = dsmad_handle,
115 .flags = HMAT_LB_MEM_MEMORY,
116 .data_type = HMAT_LB_DATA_READ_BANDWIDTH,
117 .entry_base_unit = 1000, /* GB/s */
118 .entry[0] = 16,
119 };
120
121 dslbis3 = g_malloc(sizeof(*dslbis3));
122 *dslbis3 = (CDATDslbis) {
123 .header = {
124 .type = CDAT_TYPE_DSLBIS,
125 .length = sizeof(*dslbis3),
126 },
127 .handle = dsmad_handle,
128 .flags = HMAT_LB_MEM_MEMORY,
129 .data_type = HMAT_LB_DATA_WRITE_BANDWIDTH,
130 .entry_base_unit = 1000, /* GB/s */
131 .entry[0] = 16,
132 };
133
134 dsemts = g_malloc(sizeof(*dsemts));
135 *dsemts = (CDATDsemts) {
136 .header = {
137 .type = CDAT_TYPE_DSEMTS,
138 .length = sizeof(*dsemts),
139 },
140 .DSMAS_handle = dsmad_handle,
141 /*
142 * NV: Reserved - the non volatile from DSMAS matters
143 * V: EFI_MEMORY_SP
144 */
145 .EFI_memory_type_attr = is_pmem ? 2 : 1,
146 .DPA_offset = 0,
147 .DPA_length = size,
148 };
149
150 /* Header always at start of structure */
151 cdat_table[CT3_CDAT_DSMAS] = (CDATSubHeader *)dsmas;
152 cdat_table[CT3_CDAT_DSLBIS0] = (CDATSubHeader *)dslbis0;
153 cdat_table[CT3_CDAT_DSLBIS1] = (CDATSubHeader *)dslbis1;
154 cdat_table[CT3_CDAT_DSLBIS2] = (CDATSubHeader *)dslbis2;
155 cdat_table[CT3_CDAT_DSLBIS3] = (CDATSubHeader *)dslbis3;
156 cdat_table[CT3_CDAT_DSEMTS] = (CDATSubHeader *)dsemts;
157 }
158
159 static int ct3_build_cdat_table(CDATSubHeader ***cdat_table, void *priv)
160 {
161 g_autofree CDATSubHeader **table = NULL;
162 CXLType3Dev *ct3d = priv;
163 MemoryRegion *volatile_mr = NULL, *nonvolatile_mr = NULL;
164 MemoryRegion *dc_mr = NULL;
165 uint64_t vmr_size = 0, pmr_size = 0;
166 int dsmad_handle = 0;
167 int cur_ent = 0;
168 int len = 0;
169
170 if (!ct3d->hostpmem && !ct3d->hostvmem && !ct3d->dc.num_regions) {
171 return 0;
172 }
173
174 if (ct3d->hostvmem) {
175 volatile_mr = host_memory_backend_get_memory(ct3d->hostvmem);
176 if (!volatile_mr) {
177 return -EINVAL;
178 }
179 len += CT3_CDAT_NUM_ENTRIES;
180 vmr_size = memory_region_size(volatile_mr);
181 }
182
183 if (ct3d->hostpmem) {
184 nonvolatile_mr = host_memory_backend_get_memory(ct3d->hostpmem);
185 if (!nonvolatile_mr) {
186 return -EINVAL;
187 }
188 len += CT3_CDAT_NUM_ENTRIES;
189 pmr_size = memory_region_size(nonvolatile_mr);
190 }
191
192 if (ct3d->dc.num_regions) {
193 if (!ct3d->dc.host_dc) {
194 return -EINVAL;
195 }
196 dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
197 if (!dc_mr) {
198 return -EINVAL;
199 }
200 len += CT3_CDAT_NUM_ENTRIES * ct3d->dc.num_regions;
201 }
202
203 table = g_malloc0(len * sizeof(*table));
204
205 /* Now fill them in */
206 if (volatile_mr) {
207 ct3_build_cdat_entries_for_mr(table, dsmad_handle++, vmr_size,
208 false, false, 0);
209 cur_ent = CT3_CDAT_NUM_ENTRIES;
210 }
211
212 if (nonvolatile_mr) {
213 uint64_t base = vmr_size;
214 ct3_build_cdat_entries_for_mr(&(table[cur_ent]), dsmad_handle++,
215 pmr_size, true, false, base);
216 cur_ent += CT3_CDAT_NUM_ENTRIES;
217 }
218
219 if (dc_mr) {
220 int i;
221 uint64_t region_base = vmr_size + pmr_size;
222
223 /*
224 * We assume the dynamic capacity to be volatile for now.
225 * Non-volatile dynamic capacity will be added if needed in the
226 * future.
227 */
228 for (i = 0; i < ct3d->dc.num_regions; i++) {
229 ct3d->dc.regions[i].nonvolatile = false;
230 ct3d->dc.regions[i].sharable = false;
231 ct3d->dc.regions[i].hw_managed_coherency = false;
232 ct3d->dc.regions[i].ic_specific_dc_management = false;
233 ct3d->dc.regions[i].rdonly = false;
234 ct3_build_cdat_entries_for_mr(&(table[cur_ent]),
235 dsmad_handle++,
236 ct3d->dc.regions[i].len,
237 ct3d->dc.regions[i].nonvolatile,
238 true, region_base);
239 ct3d->dc.regions[i].dsmadhandle = dsmad_handle - 1;
240
241 cur_ent += CT3_CDAT_NUM_ENTRIES;
242 region_base += ct3d->dc.regions[i].len;
243 }
244 }
245
246 assert(len == cur_ent);
247
248 *cdat_table = g_steal_pointer(&table);
249
250 return len;
251 }
252
253 static void ct3_free_cdat_table(CDATSubHeader **cdat_table, int num, void *priv)
254 {
255 int i;
256
257 for (i = 0; i < num; i++) {
258 g_free(cdat_table[i]);
259 }
260 g_free(cdat_table);
261 }
262
263 static bool cxl_doe_cdat_rsp(DOECap *doe_cap)
264 {
265 CDATObject *cdat = &CXL_TYPE3(doe_cap->pdev)->cxl_cstate.cdat;
266 uint16_t ent;
267 void *base;
268 uint32_t len;
269 CDATReq *req = pcie_doe_get_write_mbox_ptr(doe_cap);
270 CDATRsp rsp;
271
272 assert(cdat->entry_len);
273
274 /* Discard if request length mismatched */
275 if (pcie_doe_get_obj_len(req) <
276 DIV_ROUND_UP(sizeof(CDATReq), DWORD_BYTE)) {
277 return false;
278 }
279
280 ent = req->entry_handle;
281 if (ent >= cdat->entry_len) {
282 return false;
283 }
284 base = cdat->entry[ent].base;
285 len = cdat->entry[ent].length;
286
287 rsp = (CDATRsp) {
288 .header = {
289 .vendor_id = CXL_VENDOR_ID,
290 .data_obj_type = CXL_DOE_TABLE_ACCESS,
291 .reserved = 0x0,
292 .length = DIV_ROUND_UP((sizeof(rsp) + len), DWORD_BYTE),
293 },
294 .rsp_code = CXL_DOE_TAB_RSP,
295 .table_type = CXL_DOE_TAB_TYPE_CDAT,
296 .entry_handle = (ent < cdat->entry_len - 1) ?
297 ent + 1 : CXL_DOE_TAB_ENT_MAX,
298 };
299
300 memcpy(doe_cap->read_mbox, &rsp, sizeof(rsp));
301 memcpy(doe_cap->read_mbox + DIV_ROUND_UP(sizeof(rsp), DWORD_BYTE),
302 base, len);
303
304 doe_cap->read_mbox_len += rsp.header.length;
305
306 return true;
307 }
308
309 static uint32_t ct3d_config_read(PCIDevice *pci_dev, uint32_t addr, int size)
310 {
311 CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
312 uint32_t val;
313
314 if (pcie_doe_read_config(&ct3d->doe_cdat, addr, size, &val)) {
315 return val;
316 }
317
318 return pci_default_read_config(pci_dev, addr, size);
319 }
320
321 static void ct3d_config_write(PCIDevice *pci_dev, uint32_t addr, uint32_t val,
322 int size)
323 {
324 CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
325
326 pcie_doe_write_config(&ct3d->doe_cdat, addr, val, size);
327 pci_default_write_config(pci_dev, addr, val, size);
328 pcie_aer_write_config(pci_dev, addr, val, size);
329 }
330
331 /*
332 * Null value of all Fs suggested by IEEE RA guidelines for use of
333 * EU, OUI and CID
334 */
335 #define UI64_NULL ~(0ULL)
336
337 static void build_dvsecs(CXLType3Dev *ct3d)
338 {
339 CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
340 uint8_t *dvsec;
341 uint32_t range1_size_hi, range1_size_lo,
342 range1_base_hi = 0, range1_base_lo = 0,
343 range2_size_hi = 0, range2_size_lo = 0,
344 range2_base_hi = 0, range2_base_lo = 0;
345
346 /*
347 * Volatile memory is mapped as (0x0)
348 * Persistent memory is mapped at (volatile->size)
349 */
350 if (ct3d->hostvmem) {
351 range1_size_hi = ct3d->hostvmem->size >> 32;
352 range1_size_lo = (2 << 5) | (2 << 2) | 0x3 |
353 (ct3d->hostvmem->size & 0xF0000000);
354 if (ct3d->hostpmem) {
355 range2_size_hi = ct3d->hostpmem->size >> 32;
356 range2_size_lo = (2 << 5) | (2 << 2) | 0x3 |
357 (ct3d->hostpmem->size & 0xF0000000);
358 }
359 } else if (ct3d->hostpmem) {
360 range1_size_hi = ct3d->hostpmem->size >> 32;
361 range1_size_lo = (2 << 5) | (2 << 2) | 0x3 |
362 (ct3d->hostpmem->size & 0xF0000000);
363 } else {
364 /*
365 * For DCD with no static memory, set memory active, memory class bits.
366 * No range is set.
367 */
368 range1_size_hi = 0;
369 range1_size_lo = (2 << 5) | (2 << 2) | 0x3;
370 }
371
372 dvsec = (uint8_t *)&(CXLDVSECDevice){
373 .cap = 0x1e,
374 .ctrl = 0x2,
375 .status2 = 0x2,
376 .range1_size_hi = range1_size_hi,
377 .range1_size_lo = range1_size_lo,
378 .range1_base_hi = range1_base_hi,
379 .range1_base_lo = range1_base_lo,
380 .range2_size_hi = range2_size_hi,
381 .range2_size_lo = range2_size_lo,
382 .range2_base_hi = range2_base_hi,
383 .range2_base_lo = range2_base_lo,
384 };
385 cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
386 PCIE_CXL_DEVICE_DVSEC_LENGTH,
387 PCIE_CXL_DEVICE_DVSEC,
388 PCIE_CXL31_DEVICE_DVSEC_REVID, dvsec);
389
390 dvsec = (uint8_t *)&(CXLDVSECRegisterLocator){
391 .rsvd = 0,
392 .reg0_base_lo = RBI_COMPONENT_REG | CXL_COMPONENT_REG_BAR_IDX,
393 .reg0_base_hi = 0,
394 .reg1_base_lo = RBI_CXL_DEVICE_REG | CXL_DEVICE_REG_BAR_IDX,
395 .reg1_base_hi = 0,
396 };
397 cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
398 REG_LOC_DVSEC_LENGTH, REG_LOC_DVSEC,
399 REG_LOC_DVSEC_REVID, dvsec);
400 dvsec = (uint8_t *)&(CXLDVSECDeviceGPF){
401 .phase2_duration = 0x603, /* 3 seconds */
402 .phase2_power = 0x33, /* 0x33 miliwatts */
403 };
404 cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
405 GPF_DEVICE_DVSEC_LENGTH, GPF_DEVICE_DVSEC,
406 GPF_DEVICE_DVSEC_REVID, dvsec);
407
408 dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
409 .cap = 0x26, /* 68B, IO, Mem, non-MLD */
410 .ctrl = 0x02, /* IO always enabled */
411 .status = ct3d->flitmode ? 0x6 : 0x26, /* lack of 68B */
412 .rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
413 };
414 cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
415 PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH,
416 PCIE_FLEXBUS_PORT_DVSEC,
417 PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec);
418 }
419
420 static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
421 {
422 int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
423 ComponentRegisters *cregs = &ct3d->cxl_cstate.crb;
424 uint32_t *cache_mem = cregs->cache_mem_registers;
425 uint32_t ctrl;
426
427 ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc);
428 /* TODO: Sanity checks that the decoder is possible */
429 ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
430 ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
431
432 stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl);
433
434 cfmws_update_non_interleaved(true);
435 }
436
437 static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
438 {
439 int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
440 ComponentRegisters *cregs = &ct3d->cxl_cstate.crb;
441 uint32_t *cache_mem = cregs->cache_mem_registers;
442 uint32_t ctrl;
443
444 ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc);
445
446 ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
447 ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 0);
448
449 stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl);
450
451 cfmws_update_non_interleaved(false);
452 }
453
454 static int ct3d_qmp_uncor_err_to_cxl(CxlUncorErrorType qmp_err)
455 {
456 switch (qmp_err) {
457 case CXL_UNCOR_ERROR_TYPE_CACHE_DATA_PARITY:
458 return CXL_RAS_UNC_ERR_CACHE_DATA_PARITY;
459 case CXL_UNCOR_ERROR_TYPE_CACHE_ADDRESS_PARITY:
460 return CXL_RAS_UNC_ERR_CACHE_ADDRESS_PARITY;
461 case CXL_UNCOR_ERROR_TYPE_CACHE_BE_PARITY:
462 return CXL_RAS_UNC_ERR_CACHE_BE_PARITY;
463 case CXL_UNCOR_ERROR_TYPE_CACHE_DATA_ECC:
464 return CXL_RAS_UNC_ERR_CACHE_DATA_ECC;
465 case CXL_UNCOR_ERROR_TYPE_MEM_DATA_PARITY:
466 return CXL_RAS_UNC_ERR_MEM_DATA_PARITY;
467 case CXL_UNCOR_ERROR_TYPE_MEM_ADDRESS_PARITY:
468 return CXL_RAS_UNC_ERR_MEM_ADDRESS_PARITY;
469 case CXL_UNCOR_ERROR_TYPE_MEM_BE_PARITY:
470 return CXL_RAS_UNC_ERR_MEM_BE_PARITY;
471 case CXL_UNCOR_ERROR_TYPE_MEM_DATA_ECC:
472 return CXL_RAS_UNC_ERR_MEM_DATA_ECC;
473 case CXL_UNCOR_ERROR_TYPE_REINIT_THRESHOLD:
474 return CXL_RAS_UNC_ERR_REINIT_THRESHOLD;
475 case CXL_UNCOR_ERROR_TYPE_RSVD_ENCODING:
476 return CXL_RAS_UNC_ERR_RSVD_ENCODING;
477 case CXL_UNCOR_ERROR_TYPE_POISON_RECEIVED:
478 return CXL_RAS_UNC_ERR_POISON_RECEIVED;
479 case CXL_UNCOR_ERROR_TYPE_RECEIVER_OVERFLOW:
480 return CXL_RAS_UNC_ERR_RECEIVER_OVERFLOW;
481 case CXL_UNCOR_ERROR_TYPE_INTERNAL:
482 return CXL_RAS_UNC_ERR_INTERNAL;
483 case CXL_UNCOR_ERROR_TYPE_CXL_IDE_TX:
484 return CXL_RAS_UNC_ERR_CXL_IDE_TX;
485 case CXL_UNCOR_ERROR_TYPE_CXL_IDE_RX:
486 return CXL_RAS_UNC_ERR_CXL_IDE_RX;
487 default:
488 return -EINVAL;
489 }
490 }
491
492 static int ct3d_qmp_cor_err_to_cxl(CxlCorErrorType qmp_err)
493 {
494 switch (qmp_err) {
495 case CXL_COR_ERROR_TYPE_CACHE_DATA_ECC:
496 return CXL_RAS_COR_ERR_CACHE_DATA_ECC;
497 case CXL_COR_ERROR_TYPE_MEM_DATA_ECC:
498 return CXL_RAS_COR_ERR_MEM_DATA_ECC;
499 case CXL_COR_ERROR_TYPE_CRC_THRESHOLD:
500 return CXL_RAS_COR_ERR_CRC_THRESHOLD;
501 case CXL_COR_ERROR_TYPE_RETRY_THRESHOLD:
502 return CXL_RAS_COR_ERR_RETRY_THRESHOLD;
503 case CXL_COR_ERROR_TYPE_CACHE_POISON_RECEIVED:
504 return CXL_RAS_COR_ERR_CACHE_POISON_RECEIVED;
505 case CXL_COR_ERROR_TYPE_MEM_POISON_RECEIVED:
506 return CXL_RAS_COR_ERR_MEM_POISON_RECEIVED;
507 case CXL_COR_ERROR_TYPE_PHYSICAL:
508 return CXL_RAS_COR_ERR_PHYSICAL;
509 default:
510 return -EINVAL;
511 }
512 }
513
514 static void ct3d_reg_write(void *opaque, hwaddr offset, uint64_t value,
515 unsigned size)
516 {
517 CXLComponentState *cxl_cstate = opaque;
518 ComponentRegisters *cregs = &cxl_cstate->crb;
519 CXLType3Dev *ct3d = container_of(cxl_cstate, CXLType3Dev, cxl_cstate);
520 uint32_t *cache_mem = cregs->cache_mem_registers;
521 bool should_commit = false;
522 bool should_uncommit = false;
523 int which_hdm = -1;
524
525 assert(size == 4);
526 g_assert(offset < CXL2_COMPONENT_CM_REGION_SIZE);
527
528 switch (offset) {
529 case A_CXL_HDM_DECODER0_CTRL:
530 should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
531 should_uncommit = !should_commit;
532 which_hdm = 0;
533 break;
534 case A_CXL_HDM_DECODER1_CTRL:
535 should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
536 should_uncommit = !should_commit;
537 which_hdm = 1;
538 break;
539 case A_CXL_HDM_DECODER2_CTRL:
540 should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
541 should_uncommit = !should_commit;
542 which_hdm = 2;
543 break;
544 case A_CXL_HDM_DECODER3_CTRL:
545 should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
546 should_uncommit = !should_commit;
547 which_hdm = 3;
548 break;
549 case A_CXL_RAS_UNC_ERR_STATUS:
550 {
551 uint32_t capctrl = ldl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL);
552 uint32_t fe = FIELD_EX32(capctrl, CXL_RAS_ERR_CAP_CTRL,
553 FIRST_ERROR_POINTER);
554 CXLError *cxl_err;
555 uint32_t unc_err;
556
557 /*
558 * If single bit written that corresponds to the first error
559 * pointer being cleared, update the status and header log.
560 */
561 if (!QTAILQ_EMPTY(&ct3d->error_list)) {
562 if ((1 << fe) ^ value) {
563 CXLError *cxl_next;
564 /*
565 * Software is using wrong flow for multiple header recording
566 * Following behavior in PCIe r6.0 and assuming multiple
567 * header support. Implementation defined choice to clear all
568 * matching records if more than one bit set - which corresponds
569 * closest to behavior of hardware not capable of multiple
570 * header recording.
571 */
572 QTAILQ_FOREACH_SAFE(cxl_err, &ct3d->error_list, node,
573 cxl_next) {
574 if ((1 << cxl_err->type) & value) {
575 QTAILQ_REMOVE(&ct3d->error_list, cxl_err, node);
576 g_free(cxl_err);
577 }
578 }
579 } else {
580 /* Done with previous FE, so drop from list */
581 cxl_err = QTAILQ_FIRST(&ct3d->error_list);
582 QTAILQ_REMOVE(&ct3d->error_list, cxl_err, node);
583 g_free(cxl_err);
584 }
585
586 /*
587 * If there is another FE, then put that in place and update
588 * the header log
589 */
590 if (!QTAILQ_EMPTY(&ct3d->error_list)) {
591 uint32_t *header_log = &cache_mem[R_CXL_RAS_ERR_HEADER0];
592 int i;
593
594 cxl_err = QTAILQ_FIRST(&ct3d->error_list);
595 for (i = 0; i < CXL_RAS_ERR_HEADER_NUM; i++) {
596 stl_le_p(header_log + i, cxl_err->header[i]);
597 }
598 capctrl = FIELD_DP32(capctrl, CXL_RAS_ERR_CAP_CTRL,
599 FIRST_ERROR_POINTER, cxl_err->type);
600 } else {
601 /*
602 * If no more errors, then follow recommendation of PCI spec
603 * r6.0 6.2.4.2 to set the first error pointer to a status
604 * bit that will never be used.
605 */
606 capctrl = FIELD_DP32(capctrl, CXL_RAS_ERR_CAP_CTRL,
607 FIRST_ERROR_POINTER,
608 CXL_RAS_UNC_ERR_CXL_UNUSED);
609 }
610 stl_le_p((uint8_t *)cache_mem + A_CXL_RAS_ERR_CAP_CTRL, capctrl);
611 }
612 unc_err = 0;
613 QTAILQ_FOREACH(cxl_err, &ct3d->error_list, node) {
614 unc_err |= 1 << cxl_err->type;
615 }
616 stl_le_p((uint8_t *)cache_mem + offset, unc_err);
617
618 return;
619 }
620 case A_CXL_RAS_COR_ERR_STATUS:
621 {
622 uint32_t rw1c = value;
623 uint32_t temp = ldl_le_p((uint8_t *)cache_mem + offset);
624 temp &= ~rw1c;
625 stl_le_p((uint8_t *)cache_mem + offset, temp);
626 return;
627 }
628 default:
629 break;
630 }
631
632 stl_le_p((uint8_t *)cache_mem + offset, value);
633 if (should_commit) {
634 hdm_decoder_commit(ct3d, which_hdm);
635 } else if (should_uncommit) {
636 hdm_decoder_uncommit(ct3d, which_hdm);
637 }
638 }
639
640 /*
641 * TODO: dc region configuration will be updated once host backend and address
642 * space support is added for DCD.
643 */
644 static bool cxl_create_dc_regions(CXLType3Dev *ct3d, Error **errp)
645 {
646 int i;
647 uint64_t region_base = 0;
648 uint64_t region_len;
649 uint64_t decode_len;
650 uint64_t blk_size = 2 * MiB;
651 /* Only 1 block size is supported for now. */
652 uint64_t supported_blk_size_bitmask = blk_size;
653 CXLDCRegion *region;
654 MemoryRegion *mr;
655 uint64_t dc_size;
656
657 mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
658 dc_size = memory_region_size(mr);
659 region_len = DIV_ROUND_UP(dc_size, ct3d->dc.num_regions);
660
661 if (dc_size % (ct3d->dc.num_regions * CXL_CAPACITY_MULTIPLIER) != 0) {
662 error_setg(errp,
663 "backend size is not multiple of region len: 0x%" PRIx64,
664 region_len);
665 return false;
666 }
667 if (region_len % CXL_CAPACITY_MULTIPLIER != 0) {
668 error_setg(errp, "DC region size is unaligned to 0x%" PRIx64,
669 CXL_CAPACITY_MULTIPLIER);
670 return false;
671 }
672 decode_len = region_len;
673
674 if (ct3d->hostvmem) {
675 mr = host_memory_backend_get_memory(ct3d->hostvmem);
676 region_base += memory_region_size(mr);
677 }
678 if (ct3d->hostpmem) {
679 mr = host_memory_backend_get_memory(ct3d->hostpmem);
680 region_base += memory_region_size(mr);
681 }
682 if (region_base % CXL_CAPACITY_MULTIPLIER != 0) {
683 error_setg(errp, "DC region base not aligned to 0x%" PRIx64,
684 CXL_CAPACITY_MULTIPLIER);
685 return false;
686 }
687
688 for (i = 0, region = &ct3d->dc.regions[0];
689 i < ct3d->dc.num_regions;
690 i++, region++, region_base += region_len) {
691 *region = (CXLDCRegion) {
692 .base = region_base,
693 .decode_len = decode_len,
694 .len = region_len,
695 .block_size = blk_size,
696 /* dsmad_handle set when creating CDAT table entries */
697 .flags = 0,
698 .supported_blk_size_bitmask = supported_blk_size_bitmask,
699 };
700 ct3d->dc.total_capacity += region->len;
701 region->blk_bitmap = bitmap_new(region->len / region->block_size);
702 qemu_mutex_init(&region->bitmap_lock);
703 }
704 QTAILQ_INIT(&ct3d->dc.extents);
705 QTAILQ_INIT(&ct3d->dc.extents_pending);
706
707 return true;
708 }
709
710 static void cxl_destroy_dc_regions(CXLType3Dev *ct3d)
711 {
712 CXLDCExtent *ent, *ent_next;
713 CXLDCExtentGroup *group, *group_next;
714 int i;
715 CXLDCRegion *region;
716
717 QTAILQ_FOREACH_SAFE(ent, &ct3d->dc.extents, node, ent_next) {
718 cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent);
719 }
720
721 QTAILQ_FOREACH_SAFE(group, &ct3d->dc.extents_pending, node, group_next) {
722 QTAILQ_REMOVE(&ct3d->dc.extents_pending, group, node);
723 QTAILQ_FOREACH_SAFE(ent, &group->list, node, ent_next) {
724 cxl_remove_extent_from_extent_list(&group->list, ent);
725 }
726 g_free(group);
727 }
728
729 for (i = 0; i < ct3d->dc.num_regions; i++) {
730 region = &ct3d->dc.regions[i];
731 g_free(region->blk_bitmap);
732 }
733 }
734
735 static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
736 {
737 DeviceState *ds = DEVICE(ct3d);
738
739 if (!ct3d->hostmem && !ct3d->hostvmem && !ct3d->hostpmem
740 && !ct3d->dc.num_regions) {
741 error_setg(errp, "at least one memdev property must be set");
742 return false;
743 } else if (ct3d->hostmem && ct3d->hostpmem) {
744 error_setg(errp, "[memdev] cannot be used with new "
745 "[persistent-memdev] property");
746 return false;
747 } else if (ct3d->hostmem) {
748 /* Use of hostmem property implies pmem */
749 ct3d->hostpmem = ct3d->hostmem;
750 ct3d->hostmem = NULL;
751 }
752
753 if (ct3d->hostpmem && !ct3d->lsa) {
754 error_setg(errp, "lsa property must be set for persistent devices");
755 return false;
756 }
757
758 if (!ct3d->flitmode && ct3d->hdmdb) {
759 error_setg(errp, "hdm-db requires operating in 256b flit");
760 return false;
761 }
762
763 if (ct3d->hostvmem) {
764 MemoryRegion *vmr;
765 char *v_name;
766
767 vmr = host_memory_backend_get_memory(ct3d->hostvmem);
768 if (!vmr) {
769 error_setg(errp, "volatile memdev must have backing device");
770 return false;
771 }
772 if (host_memory_backend_is_mapped(ct3d->hostvmem)) {
773 error_setg(errp, "memory backend %s can't be used multiple times.",
774 object_get_canonical_path_component(OBJECT(ct3d->hostvmem)));
775 return false;
776 }
777 memory_region_set_nonvolatile(vmr, false);
778 memory_region_set_enabled(vmr, true);
779 host_memory_backend_set_mapped(ct3d->hostvmem, true);
780 if (ds->id) {
781 v_name = g_strdup_printf("cxl-type3-dpa-vmem-space:%s", ds->id);
782 } else {
783 v_name = g_strdup("cxl-type3-dpa-vmem-space");
784 }
785 address_space_init(&ct3d->hostvmem_as, vmr, v_name);
786 ct3d->cxl_dstate.vmem_size = memory_region_size(vmr);
787 ct3d->cxl_dstate.static_mem_size += memory_region_size(vmr);
788 g_free(v_name);
789 }
790
791 if (ct3d->hostpmem) {
792 MemoryRegion *pmr;
793 char *p_name;
794
795 pmr = host_memory_backend_get_memory(ct3d->hostpmem);
796 if (!pmr) {
797 error_setg(errp, "persistent memdev must have backing device");
798 return false;
799 }
800 if (host_memory_backend_is_mapped(ct3d->hostpmem)) {
801 error_setg(errp, "memory backend %s can't be used multiple times.",
802 object_get_canonical_path_component(OBJECT(ct3d->hostpmem)));
803 return false;
804 }
805 memory_region_set_nonvolatile(pmr, true);
806 memory_region_set_enabled(pmr, true);
807 host_memory_backend_set_mapped(ct3d->hostpmem, true);
808 if (ds->id) {
809 p_name = g_strdup_printf("cxl-type3-dpa-pmem-space:%s", ds->id);
810 } else {
811 p_name = g_strdup("cxl-type3-dpa-pmem-space");
812 }
813 address_space_init(&ct3d->hostpmem_as, pmr, p_name);
814 ct3d->cxl_dstate.pmem_size = memory_region_size(pmr);
815 ct3d->cxl_dstate.static_mem_size += memory_region_size(pmr);
816 g_free(p_name);
817 }
818
819 ct3d->dc.total_capacity = 0;
820 if (ct3d->dc.num_regions > 0) {
821 MemoryRegion *dc_mr;
822 char *dc_name;
823
824 if (!ct3d->dc.host_dc) {
825 error_setg(errp, "dynamic capacity must have a backing device");
826 return false;
827 }
828
829 dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
830 if (!dc_mr) {
831 error_setg(errp, "dynamic capacity must have a backing device");
832 return false;
833 }
834
835 if (host_memory_backend_is_mapped(ct3d->dc.host_dc)) {
836 error_setg(errp, "memory backend %s can't be used multiple times.",
837 object_get_canonical_path_component(OBJECT(ct3d->dc.host_dc)));
838 return false;
839 }
840 /*
841 * Set DC regions as volatile for now, non-volatile support can
842 * be added in the future if needed.
843 */
844 memory_region_set_nonvolatile(dc_mr, false);
845 memory_region_set_enabled(dc_mr, true);
846 host_memory_backend_set_mapped(ct3d->dc.host_dc, true);
847 if (ds->id) {
848 dc_name = g_strdup_printf("cxl-dcd-dpa-dc-space:%s", ds->id);
849 } else {
850 dc_name = g_strdup("cxl-dcd-dpa-dc-space");
851 }
852 address_space_init(&ct3d->dc.host_dc_as, dc_mr, dc_name);
853 g_free(dc_name);
854
855 if (!cxl_create_dc_regions(ct3d, errp)) {
856 error_append_hint(errp, "setup DC regions failed");
857 return false;
858 }
859 }
860
861 return true;
862 }
863
864 static DOEProtocol doe_cdat_prot[] = {
865 { CXL_VENDOR_ID, CXL_DOE_TABLE_ACCESS, cxl_doe_cdat_rsp },
866 { }
867 };
868
869 /* Initialize CXL device alerts with default threshold values. */
870 static void init_alert_config(CXLType3Dev *ct3d)
871 {
872 ct3d->alert_config = (CXLAlertConfig) {
873 .life_used_crit_alert_thresh = 75,
874 .life_used_warn_thresh = 40,
875 .over_temp_crit_alert_thresh = 35,
876 .under_temp_crit_alert_thresh = 10,
877 .over_temp_warn_thresh = 25,
878 .under_temp_warn_thresh = 20
879 };
880 }
881
882 static void ct3_realize(PCIDevice *pci_dev, Error **errp)
883 {
884 ERRP_GUARD();
885 CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
886 CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
887 ComponentRegisters *regs = &cxl_cstate->crb;
888 MemoryRegion *mr = &regs->component_registers;
889 uint8_t *pci_conf = pci_dev->config;
890 int i, rc;
891 uint16_t count;
892
893 QTAILQ_INIT(&ct3d->error_list);
894
895 if (!cxl_setup_memory(ct3d, errp)) {
896 return;
897 }
898
899 pci_config_set_prog_interface(pci_conf, 0x10);
900
901 pcie_endpoint_cap_init(pci_dev, 0x80);
902 if (ct3d->sn != UI64_NULL) {
903 pcie_dev_ser_num_init(pci_dev, 0x100, ct3d->sn);
904 cxl_cstate->dvsec_offset = 0x100 + 0x0c;
905 } else {
906 cxl_cstate->dvsec_offset = 0x100;
907 }
908
909 ct3d->cxl_cstate.pdev = pci_dev;
910 build_dvsecs(ct3d);
911
912 regs->special_ops = g_new0(MemoryRegionOps, 1);
913 regs->special_ops->write = ct3d_reg_write;
914
915 cxl_component_register_block_init(OBJECT(pci_dev), cxl_cstate,
916 TYPE_CXL_TYPE3);
917
918 pci_register_bar(
919 pci_dev, CXL_COMPONENT_REG_BAR_IDX,
920 PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, mr);
921
922 cxl_device_register_block_init(OBJECT(pci_dev), &ct3d->cxl_dstate,
923 &ct3d->cci);
924 pci_register_bar(pci_dev, CXL_DEVICE_REG_BAR_IDX,
925 PCI_BASE_ADDRESS_SPACE_MEMORY |
926 PCI_BASE_ADDRESS_MEM_TYPE_64,
927 &ct3d->cxl_dstate.device_registers);
928
929 /* MSI(-X) Initialization */
930 rc = msix_init_exclusive_bar(pci_dev, CXL_T3_MSIX_VECTOR_NR, 4, errp);
931 if (rc) {
932 goto err_free_special_ops;
933 }
934 for (i = 0; i < CXL_T3_MSIX_VECTOR_NR; i++) {
935 msix_vector_use(pci_dev, i);
936 }
937
938 /* DOE Initialization */
939 pcie_doe_init(pci_dev, &ct3d->doe_cdat, 0x190, doe_cdat_prot, true,
940 CXL_T3_MSIX_PCIE_DOE_TABLE_ACCESS);
941
942 cxl_cstate->cdat.build_cdat_table = ct3_build_cdat_table;
943 cxl_cstate->cdat.free_cdat_table = ct3_free_cdat_table;
944 cxl_cstate->cdat.private = ct3d;
945 if (!cxl_doe_cdat_init(cxl_cstate, errp)) {
946 goto err_msix_uninit;
947 }
948
949 init_alert_config(ct3d);
950 pcie_cap_deverr_init(pci_dev);
951 /* Leave a bit of room for expansion */
952 rc = pcie_aer_init(pci_dev, PCI_ERR_VER, 0x200, PCI_ERR_SIZEOF, errp);
953 if (rc) {
954 goto err_release_cdat;
955 }
956 cxl_event_init(&ct3d->cxl_dstate, CXL_T3_MSIX_EVENT_START);
957
958 /* Set default value for patrol scrub attributes */
959 ct3d->patrol_scrub_attrs.scrub_cycle_cap =
960 CXL_MEMDEV_PS_SCRUB_CYCLE_CHANGE_CAP_DEFAULT |
961 CXL_MEMDEV_PS_SCRUB_REALTIME_REPORT_CAP_DEFAULT;
962 ct3d->patrol_scrub_attrs.scrub_cycle =
963 CXL_MEMDEV_PS_CUR_SCRUB_CYCLE_DEFAULT |
964 (CXL_MEMDEV_PS_MIN_SCRUB_CYCLE_DEFAULT << 8);
965 ct3d->patrol_scrub_attrs.scrub_flags = CXL_MEMDEV_PS_ENABLE_DEFAULT;
966
967 /* Set default value for DDR5 ECS read attributes */
968 ct3d->ecs_attrs.ecs_log_cap = CXL_ECS_LOG_ENTRY_TYPE_DEFAULT;
969 for (count = 0; count < CXL_ECS_NUM_MEDIA_FRUS; count++) {
970 ct3d->ecs_attrs.fru_attrs[count].ecs_cap =
971 CXL_ECS_REALTIME_REPORT_CAP_DEFAULT;
972 ct3d->ecs_attrs.fru_attrs[count].ecs_config =
973 CXL_ECS_THRESHOLD_COUNT_DEFAULT |
974 (CXL_ECS_MODE_DEFAULT << 3);
975 /* Reserved */
976 ct3d->ecs_attrs.fru_attrs[count].ecs_flags = 0;
977 }
978
979 /* Set default values for soft-PPR attributes */
980 ct3d->soft_ppr_attrs = (CXLMemSoftPPRReadAttrs) {
981 .max_maint_latency = 0x5, /* 100 ms */
982 .op_caps = 0, /* require host involvement */
983 .op_mode = 0,
984 .maint_op_class = CXL_MEMDEV_MAINT_CLASS_PPR,
985 .maint_op_subclass = CXL_MEMDEV_MAINT_SUBCLASS_SPPR,
986 .sppr_flags = CXL_MEMDEV_SPPR_DPA_SUPPORT_FLAG |
987 CXL_MEMDEV_SPPR_MEM_SPARING_EV_REC_CAP_FLAG,
988 .restriction_flags = 0,
989 .sppr_op_mode = CXL_MEMDEV_SPPR_OP_MODE_MEM_SPARING_EV_REC_EN
990 };
991
992 /* Set default value for hard-PPR attributes */
993 ct3d->hard_ppr_attrs = (CXLMemHardPPRReadAttrs) {
994 .max_maint_latency = 0x5, /* 100 ms */
995 .op_caps = 0, /* require host involvement */
996 .op_mode = 0,
997 .maint_op_class = CXL_MEMDEV_MAINT_CLASS_PPR,
998 .maint_op_subclass = CXL_MEMDEV_MAINT_SUBCLASS_HPPR,
999 .hppr_flags = CXL_MEMDEV_HPPR_DPA_SUPPORT_FLAG |
1000 CXL_MEMDEV_HPPR_MEM_SPARING_EV_REC_CAP_FLAG,
1001 .restriction_flags = 0,
1002 .hppr_op_mode = CXL_MEMDEV_HPPR_OP_MODE_MEM_SPARING_EV_REC_EN
1003 };
1004
1005 /* Set default value for Cacheline Memory Sparing attributes */
1006 ct3d->cacheline_sparing_attrs = (CXLMemSparingReadAttrs) {
1007 .max_maint_latency = 0x5, /* 100 ms */
1008 .op_caps = 0, /* require host involvement */
1009 .op_mode = 0,
1010 .maint_op_class = CXL_MEMDEV_MAINT_CLASS_SPARING,
1011 .maint_op_subclass = CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING,
1012 .restriction_flags = CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG |
1013 CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG,
1014 };
1015
1016 /* Set default value for Row Memory Sparing attributes */
1017 ct3d->row_sparing_attrs = (CXLMemSparingReadAttrs) {
1018 .max_maint_latency = 0x5, /* 100 ms */
1019 .op_caps = 0, /* require host involvement */
1020 .op_mode = 0,
1021 .maint_op_class = CXL_MEMDEV_MAINT_CLASS_SPARING,
1022 .maint_op_subclass = CXL_MEMDEV_MAINT_SUBCLASS_ROW_SPARING,
1023 .restriction_flags = CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG |
1024 CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG,
1025 };
1026
1027 /* Set default value for Bank Memory Sparing attributes */
1028 ct3d->bank_sparing_attrs = (CXLMemSparingReadAttrs) {
1029 .max_maint_latency = 0x5, /* 100 ms */
1030 .op_caps = 0, /* require host involvement */
1031 .op_mode = 0,
1032 .maint_op_class = CXL_MEMDEV_MAINT_CLASS_SPARING,
1033 .maint_op_subclass = CXL_MEMDEV_MAINT_SUBCLASS_BANK_SPARING,
1034 .restriction_flags = CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG |
1035 CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG,
1036 };
1037
1038 /* Set default value for Rank Memory Sparing attributes */
1039 ct3d->rank_sparing_attrs = (CXLMemSparingReadAttrs) {
1040 .max_maint_latency = 0x5, /* 100 ms */
1041 .op_caps = 0, /* require host involvement */
1042 .op_mode = 0,
1043 .maint_op_class = CXL_MEMDEV_MAINT_CLASS_SPARING,
1044 .maint_op_subclass = CXL_MEMDEV_MAINT_SUBCLASS_RANK_SPARING,
1045 .restriction_flags = CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG |
1046 CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG,
1047 };
1048
1049 return;
1050
1051 err_release_cdat:
1052 cxl_doe_cdat_release(cxl_cstate);
1053 err_msix_uninit:
1054 msix_uninit_exclusive_bar(pci_dev);
1055 err_free_special_ops:
1056 g_free(regs->special_ops);
1057 if (ct3d->dc.host_dc) {
1058 cxl_destroy_dc_regions(ct3d);
1059 address_space_destroy(&ct3d->dc.host_dc_as);
1060 }
1061 if (ct3d->hostpmem) {
1062 address_space_destroy(&ct3d->hostpmem_as);
1063 }
1064 if (ct3d->hostvmem) {
1065 address_space_destroy(&ct3d->hostvmem_as);
1066 }
1067 }
1068
1069 static void ct3_exit(PCIDevice *pci_dev)
1070 {
1071 CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
1072 CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
1073 ComponentRegisters *regs = &cxl_cstate->crb;
1074
1075 pcie_aer_exit(pci_dev);
1076 cxl_doe_cdat_release(cxl_cstate);
1077 msix_uninit_exclusive_bar(pci_dev);
1078 g_free(regs->special_ops);
1079 cxl_destroy_cci(&ct3d->cci);
1080 if (ct3d->dc.host_dc) {
1081 cxl_destroy_dc_regions(ct3d);
1082 address_space_destroy(&ct3d->dc.host_dc_as);
1083 }
1084 if (ct3d->hostpmem) {
1085 address_space_destroy(&ct3d->hostpmem_as);
1086 }
1087 if (ct3d->hostvmem) {
1088 address_space_destroy(&ct3d->hostvmem_as);
1089 }
1090 }
1091
1092 /*
1093 * Mark the DPA range [dpa, dap + len - 1] to be backed and accessible. This
1094 * happens when a DC extent is added and accepted by the host.
1095 */
1096 void ct3_set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
1097 uint64_t len)
1098 {
1099 CXLDCRegion *region;
1100
1101 region = cxl_find_dc_region(ct3d, dpa, len);
1102 if (!region) {
1103 return;
1104 }
1105
1106 QEMU_LOCK_GUARD(&region->bitmap_lock);
1107 bitmap_set(region->blk_bitmap, (dpa - region->base) / region->block_size,
1108 len / region->block_size);
1109 }
1110
1111 /*
1112 * Check whether the DPA range [dpa, dpa + len - 1] is backed with DC extents.
1113 * Used when validating read/write to dc regions
1114 */
1115 bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
1116 uint64_t len)
1117 {
1118 CXLDCRegion *region;
1119 uint64_t nbits;
1120 long nr;
1121
1122 region = cxl_find_dc_region(ct3d, dpa, len);
1123 if (!region) {
1124 return false;
1125 }
1126
1127 nr = (dpa - region->base) / region->block_size;
1128 nbits = DIV_ROUND_UP(len, region->block_size);
1129 /*
1130 * if bits between [dpa, dpa + len) are all 1s, meaning the DPA range is
1131 * backed with DC extents, return true; else return false.
1132 */
1133 QEMU_LOCK_GUARD(&region->bitmap_lock);
1134 return find_next_zero_bit(region->blk_bitmap, nr + nbits, nr) == nr + nbits;
1135 }
1136
1137 /*
1138 * Mark the DPA range [dpa, dap + len - 1] to be unbacked and inaccessible.
1139 * This happens when a dc extent is released by the host.
1140 */
1141 void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
1142 uint64_t len)
1143 {
1144 CXLDCRegion *region;
1145 uint64_t nbits;
1146 long nr;
1147
1148 region = cxl_find_dc_region(ct3d, dpa, len);
1149 if (!region) {
1150 return;
1151 }
1152
1153 nr = (dpa - region->base) / region->block_size;
1154 nbits = len / region->block_size;
1155 QEMU_LOCK_GUARD(&region->bitmap_lock);
1156 bitmap_clear(region->blk_bitmap, nr, nbits);
1157 }
1158
1159 static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa)
1160 {
1161 int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
1162 uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
1163 unsigned int hdm_count;
1164 uint32_t cap;
1165 uint64_t dpa_base = 0;
1166 int i;
1167
1168 cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
1169 hdm_count = cxl_decoder_count_dec(FIELD_EX32(cap,
1170 CXL_HDM_DECODER_CAPABILITY,
1171 DECODER_COUNT));
1172
1173 for (i = 0; i < hdm_count; i++) {
1174 uint64_t decoder_base, decoder_size, hpa_offset, skip;
1175 uint32_t hdm_ctrl, low, high;
1176 int ig, iw;
1177
1178 low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc);
1179 high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc);
1180 decoder_base = ((uint64_t)high << 32) | (low & 0xf0000000);
1181
1182 low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc);
1183 high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc);
1184 decoder_size = ((uint64_t)high << 32) | (low & 0xf0000000);
1185
1186 low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_LO +
1187 i * hdm_inc);
1188 high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_HI +
1189 i * hdm_inc);
1190 skip = ((uint64_t)high << 32) | (low & 0xf0000000);
1191 dpa_base += skip;
1192
1193 hpa_offset = (uint64_t)host_addr - decoder_base;
1194
1195 hdm_ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * hdm_inc);
1196 iw = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IW);
1197 ig = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IG);
1198 if (!FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
1199 return false;
1200 }
1201 if (((uint64_t)host_addr < decoder_base) ||
1202 (hpa_offset >= decoder_size)) {
1203 int decoded_iw = cxl_interleave_ways_dec(iw, &error_fatal);
1204
1205 if (decoded_iw == 0) {
1206 return false;
1207 }
1208
1209 dpa_base += decoder_size / decoded_iw;
1210 continue;
1211 }
1212
1213 if (iw < 8) {
1214 *dpa = dpa_base +
1215 ((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
1216 ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
1217 >> iw));
1218 } else {
1219 *dpa = dpa_base +
1220 ((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
1221 ((((MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) & hpa_offset)
1222 >> (ig + iw)) / 3) << (ig + 8)));
1223 }
1224
1225 return true;
1226 }
1227 return false;
1228 }
1229
1230 static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev *ct3d,
1231 hwaddr host_addr,
1232 unsigned int size,
1233 AddressSpace **as,
1234 uint64_t *dpa_offset)
1235 {
1236 MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL;
1237 uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0;
1238
1239 if (ct3d->hostvmem) {
1240 vmr = host_memory_backend_get_memory(ct3d->hostvmem);
1241 vmr_size = memory_region_size(vmr);
1242 }
1243 if (ct3d->hostpmem) {
1244 pmr = host_memory_backend_get_memory(ct3d->hostpmem);
1245 pmr_size = memory_region_size(pmr);
1246 }
1247 if (ct3d->dc.host_dc) {
1248 dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
1249 dc_size = memory_region_size(dc_mr);
1250 }
1251
1252 if (!vmr && !pmr && !dc_mr) {
1253 return -ENODEV;
1254 }
1255
1256 if (!cxl_type3_dpa(ct3d, host_addr, dpa_offset)) {
1257 return -EINVAL;
1258 }
1259
1260 if (*dpa_offset >= vmr_size + pmr_size + dc_size) {
1261 return -EINVAL;
1262 }
1263
1264 if (*dpa_offset < vmr_size) {
1265 *as = &ct3d->hostvmem_as;
1266 } else if (*dpa_offset < vmr_size + pmr_size) {
1267 *as = &ct3d->hostpmem_as;
1268 *dpa_offset -= vmr_size;
1269 } else {
1270 if (!ct3_test_region_block_backed(ct3d, *dpa_offset, size)) {
1271 return -ENODEV;
1272 }
1273
1274 *as = &ct3d->dc.host_dc_as;
1275 *dpa_offset -= (vmr_size + pmr_size);
1276 }
1277
1278 return 0;
1279 }
1280
1281 MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
1282 unsigned size, MemTxAttrs attrs)
1283 {
1284 CXLType3Dev *ct3d = CXL_TYPE3(d);
1285 uint64_t dpa_offset = 0;
1286 AddressSpace *as = NULL;
1287 int res;
1288
1289 res = cxl_type3_hpa_to_as_and_dpa(ct3d, host_addr, size,
1290 &as, &dpa_offset);
1291 if (res) {
1292 return MEMTX_ERROR;
1293 }
1294
1295 if (cxl_dev_media_disabled(&ct3d->cxl_dstate)) {
1296 qemu_guest_getrandom_nofail(data, size);
1297 return MEMTX_OK;
1298 }
1299
1300 return address_space_read(as, dpa_offset, attrs, data, size);
1301 }
1302
1303 MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
1304 unsigned size, MemTxAttrs attrs)
1305 {
1306 CXLType3Dev *ct3d = CXL_TYPE3(d);
1307 uint64_t dpa_offset = 0;
1308 AddressSpace *as = NULL;
1309 int res;
1310
1311 res = cxl_type3_hpa_to_as_and_dpa(ct3d, host_addr, size,
1312 &as, &dpa_offset);
1313 if (res) {
1314 return MEMTX_ERROR;
1315 }
1316
1317 if (cxl_dev_media_disabled(&ct3d->cxl_dstate)) {
1318 return MEMTX_OK;
1319 }
1320
1321 return address_space_write(as, dpa_offset, attrs, &data, size);
1322 }
1323
1324 static void ct3d_reset(DeviceState *dev)
1325 {
1326 CXLType3Dev *ct3d = CXL_TYPE3(dev);
1327 uint32_t *reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1328 uint32_t *write_msk = ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;
1329
1330 pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed,
1331 ct3d->flitmode);
1332 cxl_component_register_init_common(reg_state, write_msk,
1333 CXL2_TYPE3_DEVICE, ct3d->hdmdb);
1334 cxl_device_register_init_t3(ct3d, CXL_T3_MSIX_MBOX);
1335
1336 /*
1337 * Bring up an endpoint to target with MCTP over VDM.
1338 * This device is emulating an MLD with single LD for now.
1339 */
1340 if (ct3d->vdm_fm_owned_ld_mctp_cci.initialized) {
1341 cxl_destroy_cci(&ct3d->vdm_fm_owned_ld_mctp_cci);
1342 }
1343 cxl_initialize_t3_fm_owned_ld_mctpcci(&ct3d->vdm_fm_owned_ld_mctp_cci,
1344 DEVICE(ct3d), DEVICE(ct3d),
1345 512); /* Max payload made up */
1346 if (ct3d->ld0_cci.initialized) {
1347 cxl_destroy_cci(&ct3d->ld0_cci);
1348 }
1349 cxl_initialize_t3_ld_cci(&ct3d->ld0_cci, DEVICE(ct3d), DEVICE(ct3d),
1350 512); /* Max payload made up */
1351 }
1352
1353 static const Property ct3_props[] = {
1354 DEFINE_PROP_LINK("memdev", CXLType3Dev, hostmem, TYPE_MEMORY_BACKEND,
1355 HostMemoryBackend *), /* for backward compatibility */
1356 DEFINE_PROP_LINK("persistent-memdev", CXLType3Dev, hostpmem,
1357 TYPE_MEMORY_BACKEND, HostMemoryBackend *),
1358 DEFINE_PROP_LINK("volatile-memdev", CXLType3Dev, hostvmem,
1359 TYPE_MEMORY_BACKEND, HostMemoryBackend *),
1360 DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND,
1361 HostMemoryBackend *),
1362 DEFINE_PROP_UINT64("sn", CXLType3Dev, sn, UI64_NULL),
1363 DEFINE_PROP_STRING("cdat", CXLType3Dev, cxl_cstate.cdat.filename),
1364 DEFINE_PROP_UINT8("num-dc-regions", CXLType3Dev, dc.num_regions, 0),
1365 DEFINE_PROP_LINK("volatile-dc-memdev", CXLType3Dev, dc.host_dc,
1366 TYPE_MEMORY_BACKEND, HostMemoryBackend *),
1367 DEFINE_PROP_PCIE_LINK_SPEED("x-speed", CXLType3Dev,
1368 speed, PCIE_LINK_SPEED_32),
1369 DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLType3Dev,
1370 width, PCIE_LINK_WIDTH_16),
1371 DEFINE_PROP_BOOL("x-256b-flit", CXLType3Dev, flitmode, false),
1372 DEFINE_PROP_BOOL("hdm-db", CXLType3Dev, hdmdb, false),
1373 };
1374
1375 static uint64_t get_lsa_size(CXLType3Dev *ct3d)
1376 {
1377 MemoryRegion *mr;
1378
1379 if (!ct3d->lsa) {
1380 return 0;
1381 }
1382
1383 mr = host_memory_backend_get_memory(ct3d->lsa);
1384 return memory_region_size(mr);
1385 }
1386
1387 static void validate_lsa_access(MemoryRegion *mr, uint64_t size,
1388 uint64_t offset)
1389 {
1390 assert(offset + size <= memory_region_size(mr));
1391 assert(offset + size > offset);
1392 }
1393
1394 static uint64_t get_lsa(CXLType3Dev *ct3d, void *buf, uint64_t size,
1395 uint64_t offset)
1396 {
1397 MemoryRegion *mr;
1398 void *lsa;
1399
1400 if (!ct3d->lsa) {
1401 return 0;
1402 }
1403
1404 mr = host_memory_backend_get_memory(ct3d->lsa);
1405 validate_lsa_access(mr, size, offset);
1406
1407 lsa = memory_region_get_ram_ptr(mr) + offset;
1408 memcpy(buf, lsa, size);
1409
1410 return size;
1411 }
1412
1413 static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
1414 uint64_t offset)
1415 {
1416 MemoryRegion *mr;
1417 void *lsa;
1418
1419 if (!ct3d->lsa) {
1420 return;
1421 }
1422
1423 mr = host_memory_backend_get_memory(ct3d->lsa);
1424 validate_lsa_access(mr, size, offset);
1425
1426 lsa = memory_region_get_ram_ptr(mr) + offset;
1427 memcpy(lsa, buf, size);
1428 memory_region_set_dirty(mr, offset, size);
1429
1430 /*
1431 * Just like the PMEM, if the guest is not allowed to exit gracefully, label
1432 * updates will get lost.
1433 */
1434 }
1435
1436 static bool set_cacheline(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data)
1437 {
1438 MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL;
1439 AddressSpace *as;
1440 uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0;
1441
1442 if (ct3d->hostvmem) {
1443 vmr = host_memory_backend_get_memory(ct3d->hostvmem);
1444 vmr_size = memory_region_size(vmr);
1445 }
1446 if (ct3d->hostpmem) {
1447 pmr = host_memory_backend_get_memory(ct3d->hostpmem);
1448 pmr_size = memory_region_size(pmr);
1449 }
1450 if (ct3d->dc.host_dc) {
1451 dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
1452 dc_size = memory_region_size(dc_mr);
1453 }
1454
1455 if (!vmr && !pmr && !dc_mr) {
1456 return false;
1457 }
1458
1459 if (dpa_offset + CXL_CACHE_LINE_SIZE > vmr_size + pmr_size + dc_size) {
1460 return false;
1461 }
1462
1463 if (dpa_offset < vmr_size) {
1464 as = &ct3d->hostvmem_as;
1465 } else if (dpa_offset < vmr_size + pmr_size) {
1466 as = &ct3d->hostpmem_as;
1467 dpa_offset -= vmr_size;
1468 } else {
1469 as = &ct3d->dc.host_dc_as;
1470 dpa_offset -= (vmr_size + pmr_size);
1471 }
1472
1473 address_space_write(as, dpa_offset, MEMTXATTRS_UNSPECIFIED, data,
1474 CXL_CACHE_LINE_SIZE);
1475 return true;
1476 }
1477
1478 void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d)
1479 {
1480 ct3d->poison_list_overflowed = true;
1481 ct3d->poison_list_overflow_ts =
1482 cxl_device_get_timestamp(&ct3d->cxl_dstate);
1483 }
1484
1485 void cxl_clear_poison_list_overflowed(CXLType3Dev *ct3d)
1486 {
1487 ct3d->poison_list_overflowed = false;
1488 ct3d->poison_list_overflow_ts = 0;
1489 }
1490
1491 void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t length,
1492 Error **errp)
1493 {
1494 Object *obj = object_resolve_path(path, NULL);
1495 CXLType3Dev *ct3d;
1496 CXLPoison *p;
1497
1498 if (length % 64) {
1499 error_setg(errp, "Poison injection must be in multiples of 64 bytes");
1500 return;
1501 }
1502 if (start % 64) {
1503 error_setg(errp, "Poison start address must be 64 byte aligned");
1504 return;
1505 }
1506 if (!obj) {
1507 error_setg(errp, "Unable to resolve path");
1508 return;
1509 }
1510 if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1511 error_setg(errp, "Path does not point to a CXL type 3 device");
1512 return;
1513 }
1514
1515 ct3d = CXL_TYPE3(obj);
1516
1517 QLIST_FOREACH(p, &ct3d->poison_list, node) {
1518 if ((start < p->start + p->length) && (start + length > p->start)) {
1519 error_setg(errp,
1520 "Overlap with existing poisoned region not supported");
1521 return;
1522 }
1523 }
1524
1525 p = g_new0(CXLPoison, 1);
1526 p->length = length;
1527 p->start = start;
1528 /* Different from injected via the mbox */
1529 p->type = CXL_POISON_TYPE_INTERNAL;
1530
1531 if (ct3d->poison_list_cnt < CXL_POISON_LIST_LIMIT) {
1532 QLIST_INSERT_HEAD(&ct3d->poison_list, p, node);
1533 ct3d->poison_list_cnt++;
1534 } else {
1535 if (!ct3d->poison_list_overflowed) {
1536 cxl_set_poison_list_overflowed(ct3d);
1537 }
1538 QLIST_INSERT_HEAD(&ct3d->poison_list_bkp, p, node);
1539 }
1540 }
1541
1542 /* For uncorrectable errors include support for multiple header recording */
1543 void qmp_cxl_inject_uncorrectable_errors(const char *path,
1544 CXLUncorErrorRecordList *errors,
1545 Error **errp)
1546 {
1547 Object *obj = object_resolve_path(path, NULL);
1548 static PCIEAERErr err = {};
1549 CXLType3Dev *ct3d;
1550 CXLError *cxl_err;
1551 uint32_t *reg_state;
1552 uint32_t unc_err;
1553 bool first;
1554
1555 if (!obj) {
1556 error_setg(errp, "Unable to resolve path");
1557 return;
1558 }
1559
1560 if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1561 error_setg(errp, "Path does not point to a CXL type 3 device");
1562 return;
1563 }
1564
1565 err.status = PCI_ERR_UNC_INTN;
1566 err.source_id = pci_requester_id(PCI_DEVICE(obj));
1567 err.flags = 0;
1568
1569 ct3d = CXL_TYPE3(obj);
1570
1571 first = QTAILQ_EMPTY(&ct3d->error_list);
1572 reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1573 while (errors) {
1574 uint32List *header = errors->value->header;
1575 uint8_t header_count = 0;
1576 int cxl_err_code;
1577
1578 cxl_err_code = ct3d_qmp_uncor_err_to_cxl(errors->value->type);
1579 if (cxl_err_code < 0) {
1580 error_setg(errp, "Unknown error code");
1581 return;
1582 }
1583
1584 /* If the error is masked, nothing to do here */
1585 if (!((1 << cxl_err_code) &
1586 ~ldl_le_p(reg_state + R_CXL_RAS_UNC_ERR_MASK))) {
1587 errors = errors->next;
1588 continue;
1589 }
1590
1591 cxl_err = g_malloc0(sizeof(*cxl_err));
1592
1593 cxl_err->type = cxl_err_code;
1594 while (header && header_count < 32) {
1595 cxl_err->header[header_count++] = header->value;
1596 header = header->next;
1597 }
1598 if (header_count > 32) {
1599 error_setg(errp, "Header must be 32 DWORD or less");
1600 return;
1601 }
1602 QTAILQ_INSERT_TAIL(&ct3d->error_list, cxl_err, node);
1603
1604 errors = errors->next;
1605 }
1606
1607 if (first && !QTAILQ_EMPTY(&ct3d->error_list)) {
1608 uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
1609 uint32_t capctrl = ldl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL);
1610 uint32_t *header_log = &cache_mem[R_CXL_RAS_ERR_HEADER0];
1611 int i;
1612
1613 cxl_err = QTAILQ_FIRST(&ct3d->error_list);
1614 for (i = 0; i < CXL_RAS_ERR_HEADER_NUM; i++) {
1615 stl_le_p(header_log + i, cxl_err->header[i]);
1616 }
1617
1618 capctrl = FIELD_DP32(capctrl, CXL_RAS_ERR_CAP_CTRL,
1619 FIRST_ERROR_POINTER, cxl_err->type);
1620 stl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL, capctrl);
1621 }
1622
1623 unc_err = 0;
1624 QTAILQ_FOREACH(cxl_err, &ct3d->error_list, node) {
1625 unc_err |= (1 << cxl_err->type);
1626 }
1627 if (!unc_err) {
1628 return;
1629 }
1630
1631 stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_STATUS, unc_err);
1632 pcie_aer_inject_error(PCI_DEVICE(obj), &err);
1633 }
1634
1635 void qmp_cxl_inject_correctable_error(const char *path, CxlCorErrorType type,
1636 Error **errp)
1637 {
1638 static PCIEAERErr err = {};
1639 Object *obj = object_resolve_path(path, NULL);
1640 CXLType3Dev *ct3d;
1641 uint32_t *reg_state;
1642 uint32_t cor_err;
1643 int cxl_err_type;
1644
1645 if (!obj) {
1646 error_setg(errp, "Unable to resolve path");
1647 return;
1648 }
1649 if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1650 error_setg(errp, "Path does not point to a CXL type 3 device");
1651 return;
1652 }
1653
1654 err.status = PCI_ERR_COR_INTERNAL;
1655 err.source_id = pci_requester_id(PCI_DEVICE(obj));
1656 err.flags = PCIE_AER_ERR_IS_CORRECTABLE;
1657
1658 ct3d = CXL_TYPE3(obj);
1659 reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1660 cor_err = ldl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS);
1661
1662 cxl_err_type = ct3d_qmp_cor_err_to_cxl(type);
1663 if (cxl_err_type < 0) {
1664 error_setg(errp, "Invalid COR error");
1665 return;
1666 }
1667 /* If the error is masked, nothting to do here */
1668 if (!((1 << cxl_err_type) &
1669 ~ldl_le_p(reg_state + R_CXL_RAS_COR_ERR_MASK))) {
1670 return;
1671 }
1672
1673 cor_err |= (1 << cxl_err_type);
1674 stl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS, cor_err);
1675
1676 pcie_aer_inject_error(PCI_DEVICE(obj), &err);
1677 }
1678
1679 void cxl_assign_event_header(CXLEventRecordHdr *hdr,
1680 const QemuUUID *uuid, uint32_t flags,
1681 uint8_t length, uint64_t timestamp,
1682 bool has_maint_op_class, uint8_t maint_op_class,
1683 bool has_maint_op_subclass,
1684 uint8_t maint_op_subclass,
1685 bool has_ld_id, uint16_t ld_id,
1686 bool has_head_id, uint8_t head_id)
1687 {
1688 hdr->length = length;
1689 memcpy(&hdr->id, uuid, sizeof(hdr->id));
1690 stq_le_p(&hdr->timestamp, timestamp);
1691
1692 if (has_maint_op_class) {
1693 hdr->maint_op_class = maint_op_class;
1694 } else {
1695 hdr->maint_op_class = 0;
1696 }
1697
1698 if (has_maint_op_subclass) {
1699 flags |= CXL_EVENT_REC_FLAGS_MAINT_OP_SUBCLASS_VALID;
1700 hdr->maint_op_subclass = maint_op_subclass;
1701 }
1702
1703 if (has_ld_id) {
1704 flags |= CXL_EVENT_REC_FLAGS_LD_ID_VALID;
1705 stw_le_p(&hdr->ld_id, ld_id);
1706 }
1707
1708 if (has_head_id) {
1709 flags |= CXL_EVENT_REC_FLAGS_HEAD_ID_VALID;
1710 hdr->head_id = head_id;
1711 }
1712
1713 st24_le_p(&hdr->flags, flags);
1714 }
1715
1716 static const QemuUUID gen_media_uuid = {
1717 .data = UUID(0xfbcd0a77, 0xc260, 0x417f,
1718 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6),
1719 };
1720
1721 static const QemuUUID dram_uuid = {
1722 .data = UUID(0x601dcbb3, 0x9c06, 0x4eab, 0xb8, 0xaf,
1723 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24),
1724 };
1725
1726 static const QemuUUID memory_module_uuid = {
1727 .data = UUID(0xfe927475, 0xdd59, 0x4339, 0xa5, 0x86,
1728 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74),
1729 };
1730
1731 #define CXL_GMER_VALID_CHANNEL BIT(0)
1732 #define CXL_GMER_VALID_RANK BIT(1)
1733 #define CXL_GMER_VALID_DEVICE BIT(2)
1734 #define CXL_GMER_VALID_COMPONENT BIT(3)
1735 #define CXL_GMER_VALID_COMPONENT_ID_FORMAT BIT(4)
1736
1737 #define CXL_GMER_EV_DESC_UCE BIT(0)
1738 #define CXL_GMER_EV_DESC_THRESHOLD_EVENT BIT(1)
1739 #define CXL_GMER_EV_DESC_POISON_LIST_OVERFLOW_EVENT BIT(2)
1740
1741 static int ct3d_qmp_cxl_event_log_enc(CxlEventLog log)
1742 {
1743 switch (log) {
1744 case CXL_EVENT_LOG_INFORMATIONAL:
1745 return CXL_EVENT_TYPE_INFO;
1746 case CXL_EVENT_LOG_WARNING:
1747 return CXL_EVENT_TYPE_WARN;
1748 case CXL_EVENT_LOG_FAILURE:
1749 return CXL_EVENT_TYPE_FAIL;
1750 case CXL_EVENT_LOG_FATAL:
1751 return CXL_EVENT_TYPE_FATAL;
1752 default:
1753 return -EINVAL;
1754 }
1755 }
1756
1757 static void cxl_maintenance_insert(CXLType3Dev *ct3d, uint64_t dpa,
1758 bool has_channel, uint8_t channel,
1759 bool has_rank, uint8_t rank,
1760 bool has_nibble_mask, uint32_t nibble_mask,
1761 bool has_bank_group, uint8_t bank_group,
1762 bool has_bank, uint8_t bank,
1763 bool has_row, uint32_t row,
1764 bool has_column, uint16_t column,
1765 const char *component_id,
1766 bool has_comp_id_pldm, bool is_comp_id_pldm,
1767 bool has_sub_channel, uint8_t sub_channel)
1768 {
1769 CXLMaintenance *ent, *m;
1770
1771 QLIST_FOREACH(ent, &ct3d->maint_list, node) {
1772 if (dpa == ent->dpa) {
1773 return;
1774 }
1775 }
1776 m = g_new0(CXLMaintenance, 1);
1777 m->dpa = dpa;
1778 m->validity_flags = 0;
1779
1780 if (has_channel) {
1781 m->channel = channel;
1782 m->validity_flags |= CXL_MSER_VALID_CHANNEL;
1783 }
1784 if (has_rank) {
1785 m->rank = rank;
1786 m->validity_flags |= CXL_MSER_VALID_RANK;
1787 }
1788 if (has_nibble_mask) {
1789 m->nibble_mask = nibble_mask;
1790 m->validity_flags |= CXL_MSER_VALID_NIB_MASK;
1791 }
1792 if (has_bank_group) {
1793 m->bank_group = bank_group;
1794 m->validity_flags |= CXL_MSER_VALID_BANK_GROUP;
1795 }
1796 if (has_bank) {
1797 m->bank = bank;
1798 m->validity_flags |= CXL_MSER_VALID_BANK;
1799 }
1800 if (has_row) {
1801 m->row = row;
1802 m->validity_flags |= CXL_MSER_VALID_ROW;
1803 }
1804 if (has_column) {
1805 m->column = column;
1806 m->validity_flags |= CXL_MSER_VALID_COLUMN;
1807 }
1808 if (has_sub_channel) {
1809 m->sub_channel = sub_channel;
1810 m->validity_flags |= CXL_MSER_VALID_SUB_CHANNEL;
1811 }
1812 if (component_id) {
1813 memcpy(m->component_id, component_id, sizeof(m->component_id));
1814 m->validity_flags |= CXL_MSER_VALID_COMP_ID;
1815 if (has_comp_id_pldm && is_comp_id_pldm) {
1816 m->validity_flags |= CXL_MSER_VALID_COMP_ID_FORMAT;
1817 }
1818 }
1819
1820 QLIST_INSERT_HEAD(&ct3d->maint_list, m, node);
1821 }
1822
1823 /* Component ID is device specific. Define this as a string. */
1824 void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log,
1825 uint32_t flags, bool has_maint_op_class,
1826 uint8_t maint_op_class,
1827 bool has_maint_op_subclass,
1828 uint8_t maint_op_subclass,
1829 bool has_ld_id, uint16_t ld_id,
1830 bool has_head_id, uint8_t head_id,
1831 uint64_t dpa,
1832 uint8_t descriptor, uint8_t type,
1833 uint8_t transaction_type,
1834 bool has_channel, uint8_t channel,
1835 bool has_rank, uint8_t rank,
1836 bool has_device, uint32_t device,
1837 const char *component_id,
1838 bool has_comp_id_pldm,
1839 bool is_comp_id_pldm,
1840 bool has_cme_ev_flags,
1841 uint8_t cme_ev_flags,
1842 bool has_cme_count, uint32_t cme_count,
1843 uint8_t sub_type,
1844 Error **errp)
1845 {
1846 Object *obj = object_resolve_path(path, NULL);
1847 CXLEventGenMedia gem;
1848 CXLEventRecordHdr *hdr = &gem.hdr;
1849 CXLDeviceState *cxlds;
1850 CXLType3Dev *ct3d;
1851 uint16_t valid_flags = 0;
1852 uint8_t enc_log;
1853 int rc;
1854
1855 if (!obj) {
1856 error_setg(errp, "Unable to resolve path");
1857 return;
1858 }
1859 if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1860 error_setg(errp, "Path does not point to a CXL type 3 device");
1861 return;
1862 }
1863 ct3d = CXL_TYPE3(obj);
1864 cxlds = &ct3d->cxl_dstate;
1865
1866 rc = ct3d_qmp_cxl_event_log_enc(log);
1867 if (rc < 0) {
1868 error_setg(errp, "Unhandled error log type");
1869 return;
1870 }
1871 if (rc == CXL_EVENT_TYPE_INFO &&
1872 (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED)) {
1873 error_setg(errp, "Informational event cannot require maintenance");
1874 return;
1875 }
1876 enc_log = rc;
1877
1878 memset(&gem, 0, sizeof(gem));
1879 cxl_assign_event_header(hdr, &gen_media_uuid, flags, sizeof(gem),
1880 cxl_device_get_timestamp(&ct3d->cxl_dstate),
1881 has_maint_op_class, maint_op_class,
1882 has_maint_op_subclass, maint_op_subclass,
1883 has_ld_id, ld_id, has_head_id, head_id);
1884
1885 stq_le_p(&gem.phys_addr, dpa);
1886 gem.type = type;
1887 gem.transaction_type = transaction_type;
1888
1889 if (has_channel) {
1890 gem.channel = channel;
1891 valid_flags |= CXL_GMER_VALID_CHANNEL;
1892 }
1893
1894 if (has_rank) {
1895 gem.rank = rank;
1896 valid_flags |= CXL_GMER_VALID_RANK;
1897 }
1898
1899 if (has_device) {
1900 st24_le_p(gem.device, device);
1901 valid_flags |= CXL_GMER_VALID_DEVICE;
1902 }
1903
1904 if (component_id) {
1905 memcpy(gem.component_id, component_id, sizeof(gem.component_id));
1906 valid_flags |= CXL_GMER_VALID_COMPONENT;
1907 if (has_comp_id_pldm && is_comp_id_pldm) {
1908 valid_flags |= CXL_GMER_VALID_COMPONENT_ID_FORMAT;
1909 }
1910 }
1911
1912 stw_le_p(&gem.validity_flags, valid_flags);
1913
1914 if (has_cme_ev_flags) {
1915 gem.cme_ev_flags = cme_ev_flags;
1916 } else {
1917 gem.cme_ev_flags = 0;
1918 }
1919
1920 if (has_cme_count) {
1921 descriptor |= CXL_GMER_EV_DESC_THRESHOLD_EVENT;
1922 st24_le_p(gem.cme_count, cme_count);
1923 } else {
1924 st24_le_p(gem.cme_count, 0);
1925 }
1926 gem.descriptor = descriptor;
1927
1928 gem.sub_type = sub_type;
1929
1930 if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&gem)) {
1931 cxl_event_irq_assert(ct3d);
1932 }
1933
1934 if (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED) {
1935 cxl_maintenance_insert(ct3d, dpa, has_channel, channel,
1936 has_rank, rank,
1937 0, 0, 0, 0, 0, 0, 0, 0,
1938 0, 0, component_id,
1939 has_comp_id_pldm, is_comp_id_pldm,
1940 0, 0);
1941 }
1942 }
1943
1944 #define CXL_DRAM_VALID_CHANNEL BIT(0)
1945 #define CXL_DRAM_VALID_RANK BIT(1)
1946 #define CXL_DRAM_VALID_NIBBLE_MASK BIT(2)
1947 #define CXL_DRAM_VALID_BANK_GROUP BIT(3)
1948 #define CXL_DRAM_VALID_BANK BIT(4)
1949 #define CXL_DRAM_VALID_ROW BIT(5)
1950 #define CXL_DRAM_VALID_COLUMN BIT(6)
1951 #define CXL_DRAM_VALID_CORRECTION_MASK BIT(7)
1952 #define CXL_DRAM_VALID_COMPONENT BIT(8)
1953 #define CXL_DRAM_VALID_COMPONENT_ID_FORMAT BIT(9)
1954 #define CXL_DRAM_VALID_SUB_CHANNEL BIT(10)
1955
1956 #define CXL_DRAM_EV_DESC_UCE BIT(0)
1957 #define CXL_DRAM_EV_DESC_THRESHOLD_EVENT BIT(1)
1958 #define CXL_DRAM_EV_DESC_POISON_LIST_OVERFLOW_EVENT BIT(2)
1959
1960 void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log,
1961 uint32_t flags,
1962 bool has_maint_op_class, uint8_t maint_op_class,
1963 bool has_maint_op_subclass,
1964 uint8_t maint_op_subclass,
1965 bool has_ld_id, uint16_t ld_id,
1966 bool has_head_id, uint8_t head_id,
1967 uint64_t dpa, uint8_t descriptor,
1968 uint8_t type, uint8_t transaction_type,
1969 bool has_channel, uint8_t channel,
1970 bool has_rank, uint8_t rank,
1971 bool has_nibble_mask, uint32_t nibble_mask,
1972 bool has_bank_group, uint8_t bank_group,
1973 bool has_bank, uint8_t bank,
1974 bool has_row, uint32_t row,
1975 bool has_column, uint16_t column,
1976 bool has_correction_mask,
1977 uint64List *correction_mask,
1978 const char *component_id,
1979 bool has_comp_id_pldm, bool is_comp_id_pldm,
1980 bool has_sub_channel, uint8_t sub_channel,
1981 bool has_cme_ev_flags, uint8_t cme_ev_flags,
1982 bool has_cvme_count, uint32_t cvme_count,
1983 uint8_t sub_type,
1984 Error **errp)
1985 {
1986 Object *obj = object_resolve_path(path, NULL);
1987 CXLEventDram dram;
1988 CXLEventRecordHdr *hdr = &dram.hdr;
1989 CXLDeviceState *cxlds;
1990 CXLType3Dev *ct3d;
1991 uint16_t valid_flags = 0;
1992 uint8_t enc_log;
1993 int rc;
1994
1995 if (!obj) {
1996 error_setg(errp, "Unable to resolve path");
1997 return;
1998 }
1999 if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
2000 error_setg(errp, "Path does not point to a CXL type 3 device");
2001 return;
2002 }
2003 ct3d = CXL_TYPE3(obj);
2004 cxlds = &ct3d->cxl_dstate;
2005
2006 rc = ct3d_qmp_cxl_event_log_enc(log);
2007 if (rc < 0) {
2008 error_setg(errp, "Unhandled error log type");
2009 return;
2010 }
2011 if (rc == CXL_EVENT_TYPE_INFO &&
2012 (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED)) {
2013 error_setg(errp, "Informational event cannot require maintenance");
2014 return;
2015 }
2016 enc_log = rc;
2017
2018 memset(&dram, 0, sizeof(dram));
2019 cxl_assign_event_header(hdr, &dram_uuid, flags, sizeof(dram),
2020 cxl_device_get_timestamp(&ct3d->cxl_dstate),
2021 has_maint_op_class, maint_op_class,
2022 has_maint_op_subclass, maint_op_subclass,
2023 has_ld_id, ld_id, has_head_id, head_id);
2024 stq_le_p(&dram.phys_addr, dpa);
2025 dram.type = type;
2026 dram.transaction_type = transaction_type;
2027
2028 if (has_channel) {
2029 dram.channel = channel;
2030 valid_flags |= CXL_DRAM_VALID_CHANNEL;
2031 }
2032
2033 if (has_rank) {
2034 dram.rank = rank;
2035 valid_flags |= CXL_DRAM_VALID_RANK;
2036 }
2037
2038 if (has_nibble_mask) {
2039 st24_le_p(dram.nibble_mask, nibble_mask);
2040 valid_flags |= CXL_DRAM_VALID_NIBBLE_MASK;
2041 }
2042
2043 if (has_bank_group) {
2044 dram.bank_group = bank_group;
2045 valid_flags |= CXL_DRAM_VALID_BANK_GROUP;
2046 }
2047
2048 if (has_bank) {
2049 dram.bank = bank;
2050 valid_flags |= CXL_DRAM_VALID_BANK;
2051 }
2052
2053 if (has_row) {
2054 st24_le_p(dram.row, row);
2055 valid_flags |= CXL_DRAM_VALID_ROW;
2056 }
2057
2058 if (has_column) {
2059 stw_le_p(&dram.column, column);
2060 valid_flags |= CXL_DRAM_VALID_COLUMN;
2061 }
2062
2063 if (has_correction_mask) {
2064 int count = 0;
2065 while (correction_mask && count < 4) {
2066 stq_le_p(&dram.correction_mask[count],
2067 correction_mask->value);
2068 count++;
2069 correction_mask = correction_mask->next;
2070 }
2071 valid_flags |= CXL_DRAM_VALID_CORRECTION_MASK;
2072 }
2073
2074 if (component_id) {
2075 memcpy(dram.component_id, component_id, sizeof(dram.component_id));
2076 valid_flags |= CXL_DRAM_VALID_COMPONENT;
2077 if (has_comp_id_pldm && is_comp_id_pldm) {
2078 valid_flags |= CXL_DRAM_VALID_COMPONENT_ID_FORMAT;
2079 }
2080 }
2081
2082 if (has_sub_channel) {
2083 dram.sub_channel = sub_channel;
2084 valid_flags |= CXL_DRAM_VALID_SUB_CHANNEL;
2085 }
2086
2087 if (has_cme_ev_flags) {
2088 dram.cme_ev_flags = cme_ev_flags;
2089 } else {
2090 dram.cme_ev_flags = 0;
2091 }
2092
2093 if (has_cvme_count) {
2094 descriptor |= CXL_DRAM_EV_DESC_THRESHOLD_EVENT;
2095 st24_le_p(dram.cvme_count, cvme_count);
2096 } else {
2097 st24_le_p(dram.cvme_count, 0);
2098 }
2099 dram.descriptor = descriptor;
2100
2101 dram.sub_type = sub_type;
2102
2103 stw_le_p(&dram.validity_flags, valid_flags);
2104
2105 if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&dram)) {
2106 cxl_event_irq_assert(ct3d);
2107 }
2108
2109 if (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED) {
2110 cxl_maintenance_insert(ct3d, dpa, has_channel, channel,
2111 has_rank, rank,
2112 has_nibble_mask, nibble_mask,
2113 has_bank_group, bank_group,
2114 has_bank, bank, has_row, row,
2115 has_column, column, component_id,
2116 has_comp_id_pldm, is_comp_id_pldm,
2117 has_sub_channel, sub_channel);
2118 }
2119 }
2120
2121 #define CXL_MMER_VALID_COMPONENT BIT(0)
2122 #define CXL_MMER_VALID_COMPONENT_ID_FORMAT BIT(1)
2123
2124 void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log,
2125 uint32_t flags, bool has_maint_op_class,
2126 uint8_t maint_op_class,
2127 bool has_maint_op_subclass,
2128 uint8_t maint_op_subclass,
2129 bool has_ld_id, uint16_t ld_id,
2130 bool has_head_id, uint8_t head_id,
2131 uint8_t type,
2132 uint8_t health_status,
2133 uint8_t media_status,
2134 uint8_t additional_status,
2135 uint8_t life_used,
2136 int16_t temperature,
2137 uint32_t dirty_shutdown_count,
2138 uint32_t corrected_volatile_error_count,
2139 uint32_t corrected_persist_error_count,
2140 const char *component_id,
2141 bool has_comp_id_pldm,
2142 bool is_comp_id_pldm,
2143 uint8_t sub_type,
2144 Error **errp)
2145 {
2146 Object *obj = object_resolve_path(path, NULL);
2147 CXLEventMemoryModule module;
2148 CXLEventRecordHdr *hdr = &module.hdr;
2149 uint16_t valid_flags = 0;
2150 CXLDeviceState *cxlds;
2151 CXLType3Dev *ct3d;
2152 uint8_t enc_log;
2153 int rc;
2154
2155 if (!obj) {
2156 error_setg(errp, "Unable to resolve path");
2157 return;
2158 }
2159 if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
2160 error_setg(errp, "Path does not point to a CXL type 3 device");
2161 return;
2162 }
2163 ct3d = CXL_TYPE3(obj);
2164 cxlds = &ct3d->cxl_dstate;
2165
2166 rc = ct3d_qmp_cxl_event_log_enc(log);
2167 if (rc < 0) {
2168 error_setg(errp, "Unhandled error log type");
2169 return;
2170 }
2171 enc_log = rc;
2172
2173 memset(&module, 0, sizeof(module));
2174 cxl_assign_event_header(hdr, &memory_module_uuid, flags, sizeof(module),
2175 cxl_device_get_timestamp(&ct3d->cxl_dstate),
2176 has_maint_op_class, maint_op_class,
2177 has_maint_op_subclass, maint_op_subclass,
2178 has_ld_id, ld_id, has_head_id, head_id);
2179
2180 module.type = type;
2181 module.health_status = health_status;
2182 module.media_status = media_status;
2183 module.additional_status = additional_status;
2184 module.life_used = life_used;
2185 stw_le_p(&module.temperature, temperature);
2186 stl_le_p(&module.dirty_shutdown_count, dirty_shutdown_count);
2187 stl_le_p(&module.corrected_volatile_error_count,
2188 corrected_volatile_error_count);
2189 stl_le_p(&module.corrected_persistent_error_count,
2190 corrected_persist_error_count);
2191
2192 if (component_id) {
2193 memcpy(module.component_id, component_id, sizeof(module.component_id));
2194 valid_flags |= CXL_MMER_VALID_COMPONENT;
2195 if (has_comp_id_pldm && is_comp_id_pldm) {
2196 valid_flags |= CXL_MMER_VALID_COMPONENT_ID_FORMAT;
2197 }
2198 }
2199 module.sub_type = sub_type;
2200
2201 stw_le_p(&module.validity_flags, valid_flags);
2202
2203 if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&module)) {
2204 cxl_event_irq_assert(ct3d);
2205 }
2206 }
2207
2208 /*
2209 * Check whether the range [dpa, dpa + len - 1] has overlaps with extents in
2210 * the list.
2211 * Return value: return true if has overlaps; otherwise, return false
2212 */
2213 bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list,
2214 uint64_t dpa, uint64_t len)
2215 {
2216 CXLDCExtent *ent;
2217 Range range1, range2;
2218
2219 if (!list) {
2220 return false;
2221 }
2222
2223 range_init_nofail(&range1, dpa, len);
2224 QTAILQ_FOREACH(ent, list, node) {
2225 range_init_nofail(&range2, ent->start_dpa, ent->len);
2226 if (range_overlaps_range(&range1, &range2)) {
2227 return true;
2228 }
2229 }
2230 return false;
2231 }
2232
2233 /*
2234 * Check whether the range [dpa, dpa + len - 1] is contained by extents in
2235 * the list.
2236 * Will check multiple extents containment once superset release is added.
2237 * Return value: return true if range is contained; otherwise, return false
2238 */
2239 bool cxl_extents_contains_dpa_range(CXLDCExtentList *list,
2240 uint64_t dpa, uint64_t len)
2241 {
2242 CXLDCExtent *ent;
2243 Range range1, range2;
2244
2245 if (!list) {
2246 return false;
2247 }
2248
2249 range_init_nofail(&range1, dpa, len);
2250 QTAILQ_FOREACH(ent, list, node) {
2251 range_init_nofail(&range2, ent->start_dpa, ent->len);
2252 if (range_contains_range(&range2, &range1)) {
2253 return true;
2254 }
2255 }
2256 return false;
2257 }
2258
2259 bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list,
2260 uint64_t dpa, uint64_t len)
2261 {
2262 CXLDCExtentGroup *group;
2263
2264 if (!list) {
2265 return false;
2266 }
2267
2268 QTAILQ_FOREACH(group, list, node) {
2269 if (cxl_extents_overlaps_dpa_range(&group->list, dpa, len)) {
2270 return true;
2271 }
2272 }
2273 return false;
2274 }
2275
2276 /*
2277 * The main function to process dynamic capacity event with extent list.
2278 * Currently DC extents add/release requests are processed.
2279 */
2280 static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
2281 uint16_t hid, CXLDCEventType type, uint8_t rid,
2282 CxlDynamicCapacityExtentList *records, Error **errp)
2283 {
2284 Object *obj;
2285 CXLType3Dev *dcd;
2286 uint32_t num_extents = 0;
2287 CxlDynamicCapacityExtentList *list;
2288 CXLDCExtentGroup *group = NULL;
2289 g_autofree CXLDCExtentRaw *extents = NULL;
2290 uint64_t dpa, offset, len, block_size;
2291 g_autofree unsigned long *blk_bitmap = NULL;
2292 int i;
2293
2294 obj = object_resolve_path_type(path, TYPE_CXL_TYPE3, NULL);
2295 if (!obj) {
2296 error_setg(errp, "Unable to resolve CXL type 3 device");
2297 return;
2298 }
2299
2300 dcd = CXL_TYPE3(obj);
2301 if (!dcd->dc.num_regions) {
2302 error_setg(errp, "No dynamic capacity support from the device");
2303 return;
2304 }
2305
2306
2307 if (rid >= dcd->dc.num_regions) {
2308 error_setg(errp, "region id is too large");
2309 return;
2310 }
2311 block_size = dcd->dc.regions[rid].block_size;
2312 blk_bitmap = bitmap_new(dcd->dc.regions[rid].len / block_size);
2313
2314 /* Sanity check and count the extents */
2315 list = records;
2316 while (list) {
2317 offset = list->value->offset;
2318 len = list->value->len;
2319 dpa = offset + dcd->dc.regions[rid].base;
2320
2321 if (len == 0) {
2322 error_setg(errp, "extent with 0 length is not allowed");
2323 return;
2324 }
2325
2326 if (offset % block_size || len % block_size) {
2327 error_setg(errp, "dpa or len is not aligned to region block size");
2328 return;
2329 }
2330
2331 if (offset + len > dcd->dc.regions[rid].len) {
2332 error_setg(errp, "extent range is beyond the region end");
2333 return;
2334 }
2335
2336 /* No duplicate or overlapped extents are allowed */
2337 if (test_any_bits_set(blk_bitmap, offset / block_size,
2338 len / block_size)) {
2339 error_setg(errp, "duplicate or overlapped extents are detected");
2340 return;
2341 }
2342 bitmap_set(blk_bitmap, offset / block_size, len / block_size);
2343
2344 if (type == DC_EVENT_RELEASE_CAPACITY) {
2345 if (cxl_extent_groups_overlaps_dpa_range(&dcd->dc.extents_pending,
2346 dpa, len)) {
2347 error_setg(errp,
2348 "cannot release extent with pending DPA range");
2349 return;
2350 }
2351 if (!ct3_test_region_block_backed(dcd, dpa, len)) {
2352 error_setg(errp,
2353 "cannot release extent with non-existing DPA range");
2354 return;
2355 }
2356 } else if (type == DC_EVENT_ADD_CAPACITY) {
2357 if (cxl_extents_overlaps_dpa_range(&dcd->dc.extents, dpa, len)) {
2358 error_setg(errp,
2359 "cannot add DPA already accessible to the same LD");
2360 return;
2361 }
2362 if (cxl_extent_groups_overlaps_dpa_range(&dcd->dc.extents_pending,
2363 dpa, len)) {
2364 error_setg(errp,
2365 "cannot add DPA again while still pending");
2366 return;
2367 }
2368 }
2369 list = list->next;
2370 num_extents++;
2371 }
2372
2373 /* Create extent list for event being passed to host */
2374 i = 0;
2375 list = records;
2376 extents = g_new0(CXLDCExtentRaw, num_extents);
2377 while (list) {
2378 offset = list->value->offset;
2379 len = list->value->len;
2380 dpa = dcd->dc.regions[rid].base + offset;
2381
2382 extents[i].start_dpa = dpa;
2383 extents[i].len = len;
2384 memset(extents[i].tag, 0, 0x10);
2385 extents[i].shared_seq = 0;
2386 if (type == DC_EVENT_ADD_CAPACITY) {
2387 group = cxl_insert_extent_to_extent_group(group,
2388 extents[i].start_dpa,
2389 extents[i].len,
2390 extents[i].tag,
2391 extents[i].shared_seq);
2392 }
2393
2394 list = list->next;
2395 i++;
2396 }
2397 if (group) {
2398 cxl_extent_group_list_insert_tail(&dcd->dc.extents_pending, group);
2399 dcd->dc.total_extent_count += num_extents;
2400 }
2401
2402 cxl_create_dc_event_records_for_extents(dcd, type, extents, num_extents);
2403 }
2404
2405 void qmp_cxl_add_dynamic_capacity(const char *path, uint16_t host_id,
2406 CxlExtentSelectionPolicy sel_policy,
2407 uint8_t region, const char *tag,
2408 CxlDynamicCapacityExtentList *extents,
2409 Error **errp)
2410 {
2411 switch (sel_policy) {
2412 case CXL_EXTENT_SELECTION_POLICY_PRESCRIPTIVE:
2413 qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id,
2414 DC_EVENT_ADD_CAPACITY,
2415 region, extents, errp);
2416 return;
2417 default:
2418 error_setg(errp, "Selection policy not supported");
2419 return;
2420 }
2421 }
2422
2423 void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id,
2424 CxlExtentRemovalPolicy removal_policy,
2425 bool has_forced_removal,
2426 bool forced_removal,
2427 bool has_sanitize_on_release,
2428 bool sanitize_on_release,
2429 uint8_t region,
2430 const char *tag,
2431 CxlDynamicCapacityExtentList *extents,
2432 Error **errp)
2433 {
2434 CXLDCEventType type = DC_EVENT_RELEASE_CAPACITY;
2435
2436 if (has_forced_removal && forced_removal) {
2437 /* TODO: enable forced removal in the future */
2438 type = DC_EVENT_FORCED_RELEASE_CAPACITY;
2439 error_setg(errp, "Forced removal not supported yet");
2440 return;
2441 }
2442
2443 switch (removal_policy) {
2444 case CXL_EXTENT_REMOVAL_POLICY_PRESCRIPTIVE:
2445 qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id, type,
2446 region, extents, errp);
2447 return;
2448 default:
2449 error_setg(errp, "Removal policy not supported");
2450 return;
2451 }
2452 }
2453
2454 static void ct3_class_init(ObjectClass *oc, const void *data)
2455 {
2456 DeviceClass *dc = DEVICE_CLASS(oc);
2457 PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
2458 CXLType3Class *cvc = CXL_TYPE3_CLASS(oc);
2459
2460 pc->realize = ct3_realize;
2461 pc->exit = ct3_exit;
2462 pc->class_id = PCI_CLASS_MEMORY_CXL;
2463 pc->vendor_id = PCI_VENDOR_ID_INTEL;
2464 pc->device_id = 0xd93; /* LVF for now */
2465 pc->revision = 1;
2466
2467 pc->config_write = ct3d_config_write;
2468 pc->config_read = ct3d_config_read;
2469
2470 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2471 dc->desc = "CXL Memory Device (Type 3)";
2472 device_class_set_legacy_reset(dc, ct3d_reset);
2473 device_class_set_props(dc, ct3_props);
2474
2475 cvc->get_lsa_size = get_lsa_size;
2476 cvc->get_lsa = get_lsa;
2477 cvc->set_lsa = set_lsa;
2478 cvc->set_cacheline = set_cacheline;
2479 }
2480
2481 static const TypeInfo ct3d_info = {
2482 .name = TYPE_CXL_TYPE3,
2483 .parent = TYPE_PCI_DEVICE,
2484 .class_size = sizeof(struct CXLType3Class),
2485 .class_init = ct3_class_init,
2486 .instance_size = sizeof(CXLType3Dev),
2487 .interfaces = (const InterfaceInfo[]) {
2488 { INTERFACE_CXL_DEVICE },
2489 { INTERFACE_PCIE_DEVICE },
2490 {}
2491 },
2492 };
2493
2494 static void ct3d_registers(void)
2495 {
2496 type_register_static(&ct3d_info);
2497 }
2498
2499 type_init(ct3d_registers);