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