xref: /qemu/hw/mem/cxl_type3.c (revision fa19fe4e3a61765ff60914ee00fc1e7a6a38dba9)
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 "sysemu/hostmem.h"
29 #include "sysemu/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 = 6;
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     for (count = 0; count < CXL_ECS_NUM_MEDIA_FRUS; count++) {
924         ct3d->ecs_attrs[count].ecs_log_cap =
925                             CXL_ECS_LOG_ENTRY_TYPE_DEFAULT;
926         ct3d->ecs_attrs[count].ecs_cap =
927                             CXL_ECS_REALTIME_REPORT_CAP_DEFAULT;
928         ct3d->ecs_attrs[count].ecs_config =
929                             CXL_ECS_THRESHOLD_COUNT_DEFAULT |
930                             (CXL_ECS_MODE_DEFAULT << 3);
931         /* Reserved */
932         ct3d->ecs_attrs[count].ecs_flags = 0;
933     }
934 
935     return;
936 
937 err_release_cdat:
938     cxl_doe_cdat_release(cxl_cstate);
939 err_free_special_ops:
940     g_free(regs->special_ops);
941 err_address_space_free:
942     if (ct3d->dc.host_dc) {
943         cxl_destroy_dc_regions(ct3d);
944         address_space_destroy(&ct3d->dc.host_dc_as);
945     }
946     if (ct3d->hostpmem) {
947         address_space_destroy(&ct3d->hostpmem_as);
948     }
949     if (ct3d->hostvmem) {
950         address_space_destroy(&ct3d->hostvmem_as);
951     }
952     return;
953 }
954 
955 static void ct3_exit(PCIDevice *pci_dev)
956 {
957     CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
958     CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
959     ComponentRegisters *regs = &cxl_cstate->crb;
960 
961     pcie_aer_exit(pci_dev);
962     cxl_doe_cdat_release(cxl_cstate);
963     g_free(regs->special_ops);
964     if (ct3d->dc.host_dc) {
965         cxl_destroy_dc_regions(ct3d);
966         address_space_destroy(&ct3d->dc.host_dc_as);
967     }
968     if (ct3d->hostpmem) {
969         address_space_destroy(&ct3d->hostpmem_as);
970     }
971     if (ct3d->hostvmem) {
972         address_space_destroy(&ct3d->hostvmem_as);
973     }
974 }
975 
976 /*
977  * Mark the DPA range [dpa, dap + len - 1] to be backed and accessible. This
978  * happens when a DC extent is added and accepted by the host.
979  */
980 void ct3_set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
981                                  uint64_t len)
982 {
983     CXLDCRegion *region;
984 
985     region = cxl_find_dc_region(ct3d, dpa, len);
986     if (!region) {
987         return;
988     }
989 
990     bitmap_set(region->blk_bitmap, (dpa - region->base) / region->block_size,
991                len / region->block_size);
992 }
993 
994 /*
995  * Check whether the DPA range [dpa, dpa + len - 1] is backed with DC extents.
996  * Used when validating read/write to dc regions
997  */
998 bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
999                                   uint64_t len)
1000 {
1001     CXLDCRegion *region;
1002     uint64_t nbits;
1003     long nr;
1004 
1005     region = cxl_find_dc_region(ct3d, dpa, len);
1006     if (!region) {
1007         return false;
1008     }
1009 
1010     nr = (dpa - region->base) / region->block_size;
1011     nbits = DIV_ROUND_UP(len, region->block_size);
1012     /*
1013      * if bits between [dpa, dpa + len) are all 1s, meaning the DPA range is
1014      * backed with DC extents, return true; else return false.
1015      */
1016     return find_next_zero_bit(region->blk_bitmap, nr + nbits, nr) == nr + nbits;
1017 }
1018 
1019 /*
1020  * Mark the DPA range [dpa, dap + len - 1] to be unbacked and inaccessible.
1021  * This happens when a dc extent is released by the host.
1022  */
1023 void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
1024                                    uint64_t len)
1025 {
1026     CXLDCRegion *region;
1027     uint64_t nbits;
1028     long nr;
1029 
1030     region = cxl_find_dc_region(ct3d, dpa, len);
1031     if (!region) {
1032         return;
1033     }
1034 
1035     nr = (dpa - region->base) / region->block_size;
1036     nbits = len / region->block_size;
1037     bitmap_clear(region->blk_bitmap, nr, nbits);
1038 }
1039 
1040 static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa)
1041 {
1042     int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
1043     uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
1044     unsigned int hdm_count;
1045     uint32_t cap;
1046     uint64_t dpa_base = 0;
1047     int i;
1048 
1049     cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
1050     hdm_count = cxl_decoder_count_dec(FIELD_EX32(cap,
1051                                                  CXL_HDM_DECODER_CAPABILITY,
1052                                                  DECODER_COUNT));
1053 
1054     for (i = 0; i < hdm_count; i++) {
1055         uint64_t decoder_base, decoder_size, hpa_offset, skip;
1056         uint32_t hdm_ctrl, low, high;
1057         int ig, iw;
1058 
1059         low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc);
1060         high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc);
1061         decoder_base = ((uint64_t)high << 32) | (low & 0xf0000000);
1062 
1063         low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc);
1064         high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc);
1065         decoder_size = ((uint64_t)high << 32) | (low & 0xf0000000);
1066 
1067         low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_LO +
1068                        i * hdm_inc);
1069         high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_HI +
1070                         i * hdm_inc);
1071         skip = ((uint64_t)high << 32) | (low & 0xf0000000);
1072         dpa_base += skip;
1073 
1074         hpa_offset = (uint64_t)host_addr - decoder_base;
1075 
1076         hdm_ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * hdm_inc);
1077         iw = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IW);
1078         ig = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IG);
1079         if (!FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
1080             return false;
1081         }
1082         if (((uint64_t)host_addr < decoder_base) ||
1083             (hpa_offset >= decoder_size)) {
1084             int decoded_iw = cxl_interleave_ways_dec(iw, &error_fatal);
1085 
1086             if (decoded_iw == 0) {
1087                 return false;
1088             }
1089 
1090             dpa_base += decoder_size / decoded_iw;
1091             continue;
1092         }
1093 
1094         *dpa = dpa_base +
1095             ((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
1096              ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
1097               >> iw));
1098 
1099         return true;
1100     }
1101     return false;
1102 }
1103 
1104 static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev *ct3d,
1105                                        hwaddr host_addr,
1106                                        unsigned int size,
1107                                        AddressSpace **as,
1108                                        uint64_t *dpa_offset)
1109 {
1110     MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL;
1111     uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0;
1112 
1113     if (ct3d->hostvmem) {
1114         vmr = host_memory_backend_get_memory(ct3d->hostvmem);
1115         vmr_size = memory_region_size(vmr);
1116     }
1117     if (ct3d->hostpmem) {
1118         pmr = host_memory_backend_get_memory(ct3d->hostpmem);
1119         pmr_size = memory_region_size(pmr);
1120     }
1121     if (ct3d->dc.host_dc) {
1122         dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
1123         dc_size = memory_region_size(dc_mr);
1124     }
1125 
1126     if (!vmr && !pmr && !dc_mr) {
1127         return -ENODEV;
1128     }
1129 
1130     if (!cxl_type3_dpa(ct3d, host_addr, dpa_offset)) {
1131         return -EINVAL;
1132     }
1133 
1134     if (*dpa_offset >= vmr_size + pmr_size + dc_size) {
1135         return -EINVAL;
1136     }
1137 
1138     if (*dpa_offset < vmr_size) {
1139         *as = &ct3d->hostvmem_as;
1140     } else if (*dpa_offset < vmr_size + pmr_size) {
1141         *as = &ct3d->hostpmem_as;
1142         *dpa_offset -= vmr_size;
1143     } else {
1144         if (!ct3_test_region_block_backed(ct3d, *dpa_offset, size)) {
1145             return -ENODEV;
1146         }
1147 
1148         *as = &ct3d->dc.host_dc_as;
1149         *dpa_offset -= (vmr_size + pmr_size);
1150     }
1151 
1152     return 0;
1153 }
1154 
1155 MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
1156                            unsigned size, MemTxAttrs attrs)
1157 {
1158     CXLType3Dev *ct3d = CXL_TYPE3(d);
1159     uint64_t dpa_offset = 0;
1160     AddressSpace *as = NULL;
1161     int res;
1162 
1163     res = cxl_type3_hpa_to_as_and_dpa(ct3d, host_addr, size,
1164                                       &as, &dpa_offset);
1165     if (res) {
1166         return MEMTX_ERROR;
1167     }
1168 
1169     if (cxl_dev_media_disabled(&ct3d->cxl_dstate)) {
1170         qemu_guest_getrandom_nofail(data, size);
1171         return MEMTX_OK;
1172     }
1173 
1174     return address_space_read(as, dpa_offset, attrs, data, size);
1175 }
1176 
1177 MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
1178                             unsigned size, MemTxAttrs attrs)
1179 {
1180     CXLType3Dev *ct3d = CXL_TYPE3(d);
1181     uint64_t dpa_offset = 0;
1182     AddressSpace *as = NULL;
1183     int res;
1184 
1185     res = cxl_type3_hpa_to_as_and_dpa(ct3d, host_addr, size,
1186                                       &as, &dpa_offset);
1187     if (res) {
1188         return MEMTX_ERROR;
1189     }
1190 
1191     if (cxl_dev_media_disabled(&ct3d->cxl_dstate)) {
1192         return MEMTX_OK;
1193     }
1194 
1195     return address_space_write(as, dpa_offset, attrs, &data, size);
1196 }
1197 
1198 static void ct3d_reset(DeviceState *dev)
1199 {
1200     CXLType3Dev *ct3d = CXL_TYPE3(dev);
1201     uint32_t *reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1202     uint32_t *write_msk = ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;
1203 
1204     pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed);
1205     cxl_component_register_init_common(reg_state, write_msk, CXL2_TYPE3_DEVICE);
1206     cxl_device_register_init_t3(ct3d);
1207 
1208     /*
1209      * Bring up an endpoint to target with MCTP over VDM.
1210      * This device is emulating an MLD with single LD for now.
1211      */
1212     cxl_initialize_t3_fm_owned_ld_mctpcci(&ct3d->vdm_fm_owned_ld_mctp_cci,
1213                                           DEVICE(ct3d), DEVICE(ct3d),
1214                                           512); /* Max payload made up */
1215     cxl_initialize_t3_ld_cci(&ct3d->ld0_cci, DEVICE(ct3d), DEVICE(ct3d),
1216                              512); /* Max payload made up */
1217 
1218 }
1219 
1220 static Property ct3_props[] = {
1221     DEFINE_PROP_LINK("memdev", CXLType3Dev, hostmem, TYPE_MEMORY_BACKEND,
1222                      HostMemoryBackend *), /* for backward compatibility */
1223     DEFINE_PROP_LINK("persistent-memdev", CXLType3Dev, hostpmem,
1224                      TYPE_MEMORY_BACKEND, HostMemoryBackend *),
1225     DEFINE_PROP_LINK("volatile-memdev", CXLType3Dev, hostvmem,
1226                      TYPE_MEMORY_BACKEND, HostMemoryBackend *),
1227     DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND,
1228                      HostMemoryBackend *),
1229     DEFINE_PROP_UINT64("sn", CXLType3Dev, sn, UI64_NULL),
1230     DEFINE_PROP_STRING("cdat", CXLType3Dev, cxl_cstate.cdat.filename),
1231     DEFINE_PROP_UINT8("num-dc-regions", CXLType3Dev, dc.num_regions, 0),
1232     DEFINE_PROP_LINK("volatile-dc-memdev", CXLType3Dev, dc.host_dc,
1233                      TYPE_MEMORY_BACKEND, HostMemoryBackend *),
1234     DEFINE_PROP_PCIE_LINK_SPEED("x-speed", CXLType3Dev,
1235                                 speed, PCIE_LINK_SPEED_32),
1236     DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLType3Dev,
1237                                 width, PCIE_LINK_WIDTH_16),
1238     DEFINE_PROP_END_OF_LIST(),
1239 };
1240 
1241 static uint64_t get_lsa_size(CXLType3Dev *ct3d)
1242 {
1243     MemoryRegion *mr;
1244 
1245     if (!ct3d->lsa) {
1246         return 0;
1247     }
1248 
1249     mr = host_memory_backend_get_memory(ct3d->lsa);
1250     return memory_region_size(mr);
1251 }
1252 
1253 static void validate_lsa_access(MemoryRegion *mr, uint64_t size,
1254                                 uint64_t offset)
1255 {
1256     assert(offset + size <= memory_region_size(mr));
1257     assert(offset + size > offset);
1258 }
1259 
1260 static uint64_t get_lsa(CXLType3Dev *ct3d, void *buf, uint64_t size,
1261                     uint64_t offset)
1262 {
1263     MemoryRegion *mr;
1264     void *lsa;
1265 
1266     if (!ct3d->lsa) {
1267         return 0;
1268     }
1269 
1270     mr = host_memory_backend_get_memory(ct3d->lsa);
1271     validate_lsa_access(mr, size, offset);
1272 
1273     lsa = memory_region_get_ram_ptr(mr) + offset;
1274     memcpy(buf, lsa, size);
1275 
1276     return size;
1277 }
1278 
1279 static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
1280                     uint64_t offset)
1281 {
1282     MemoryRegion *mr;
1283     void *lsa;
1284 
1285     if (!ct3d->lsa) {
1286         return;
1287     }
1288 
1289     mr = host_memory_backend_get_memory(ct3d->lsa);
1290     validate_lsa_access(mr, size, offset);
1291 
1292     lsa = memory_region_get_ram_ptr(mr) + offset;
1293     memcpy(lsa, buf, size);
1294     memory_region_set_dirty(mr, offset, size);
1295 
1296     /*
1297      * Just like the PMEM, if the guest is not allowed to exit gracefully, label
1298      * updates will get lost.
1299      */
1300 }
1301 
1302 static bool set_cacheline(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data)
1303 {
1304     MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL;
1305     AddressSpace *as;
1306     uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0;
1307 
1308     if (ct3d->hostvmem) {
1309         vmr = host_memory_backend_get_memory(ct3d->hostvmem);
1310         vmr_size = memory_region_size(vmr);
1311     }
1312     if (ct3d->hostpmem) {
1313         pmr = host_memory_backend_get_memory(ct3d->hostpmem);
1314         pmr_size = memory_region_size(pmr);
1315     }
1316     if (ct3d->dc.host_dc) {
1317         dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
1318         dc_size = memory_region_size(dc_mr);
1319      }
1320 
1321     if (!vmr && !pmr && !dc_mr) {
1322         return false;
1323     }
1324 
1325     if (dpa_offset + CXL_CACHE_LINE_SIZE > vmr_size + pmr_size + dc_size) {
1326         return false;
1327     }
1328 
1329     if (dpa_offset < vmr_size) {
1330         as = &ct3d->hostvmem_as;
1331     } else if (dpa_offset < vmr_size + pmr_size) {
1332         as = &ct3d->hostpmem_as;
1333         dpa_offset -= vmr_size;
1334     } else {
1335         as = &ct3d->dc.host_dc_as;
1336         dpa_offset -= (vmr_size + pmr_size);
1337     }
1338 
1339     address_space_write(as, dpa_offset, MEMTXATTRS_UNSPECIFIED, data,
1340                         CXL_CACHE_LINE_SIZE);
1341     return true;
1342 }
1343 
1344 void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d)
1345 {
1346         ct3d->poison_list_overflowed = true;
1347         ct3d->poison_list_overflow_ts =
1348             cxl_device_get_timestamp(&ct3d->cxl_dstate);
1349 }
1350 
1351 void cxl_clear_poison_list_overflowed(CXLType3Dev *ct3d)
1352 {
1353     ct3d->poison_list_overflowed = false;
1354     ct3d->poison_list_overflow_ts = 0;
1355 }
1356 
1357 void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t length,
1358                            Error **errp)
1359 {
1360     Object *obj = object_resolve_path(path, NULL);
1361     CXLType3Dev *ct3d;
1362     CXLPoison *p;
1363 
1364     if (length % 64) {
1365         error_setg(errp, "Poison injection must be in multiples of 64 bytes");
1366         return;
1367     }
1368     if (start % 64) {
1369         error_setg(errp, "Poison start address must be 64 byte aligned");
1370         return;
1371     }
1372     if (!obj) {
1373         error_setg(errp, "Unable to resolve path");
1374         return;
1375     }
1376     if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1377         error_setg(errp, "Path does not point to a CXL type 3 device");
1378         return;
1379     }
1380 
1381     ct3d = CXL_TYPE3(obj);
1382 
1383     QLIST_FOREACH(p, &ct3d->poison_list, node) {
1384         if (((start >= p->start) && (start < p->start + p->length)) ||
1385             ((start + length > p->start) &&
1386              (start + length <= p->start + p->length))) {
1387             error_setg(errp,
1388                        "Overlap with existing poisoned region not supported");
1389             return;
1390         }
1391     }
1392 
1393     p = g_new0(CXLPoison, 1);
1394     p->length = length;
1395     p->start = start;
1396     /* Different from injected via the mbox */
1397     p->type = CXL_POISON_TYPE_INTERNAL;
1398 
1399     if (ct3d->poison_list_cnt < CXL_POISON_LIST_LIMIT) {
1400         QLIST_INSERT_HEAD(&ct3d->poison_list, p, node);
1401         ct3d->poison_list_cnt++;
1402     } else {
1403         if (!ct3d->poison_list_overflowed) {
1404             cxl_set_poison_list_overflowed(ct3d);
1405         }
1406         QLIST_INSERT_HEAD(&ct3d->poison_list_bkp, p, node);
1407     }
1408 }
1409 
1410 /* For uncorrectable errors include support for multiple header recording */
1411 void qmp_cxl_inject_uncorrectable_errors(const char *path,
1412                                          CXLUncorErrorRecordList *errors,
1413                                          Error **errp)
1414 {
1415     Object *obj = object_resolve_path(path, NULL);
1416     static PCIEAERErr err = {};
1417     CXLType3Dev *ct3d;
1418     CXLError *cxl_err;
1419     uint32_t *reg_state;
1420     uint32_t unc_err;
1421     bool first;
1422 
1423     if (!obj) {
1424         error_setg(errp, "Unable to resolve path");
1425         return;
1426     }
1427 
1428     if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1429         error_setg(errp, "Path does not point to a CXL type 3 device");
1430         return;
1431     }
1432 
1433     err.status = PCI_ERR_UNC_INTN;
1434     err.source_id = pci_requester_id(PCI_DEVICE(obj));
1435     err.flags = 0;
1436 
1437     ct3d = CXL_TYPE3(obj);
1438 
1439     first = QTAILQ_EMPTY(&ct3d->error_list);
1440     reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1441     while (errors) {
1442         uint32List *header = errors->value->header;
1443         uint8_t header_count = 0;
1444         int cxl_err_code;
1445 
1446         cxl_err_code = ct3d_qmp_uncor_err_to_cxl(errors->value->type);
1447         if (cxl_err_code < 0) {
1448             error_setg(errp, "Unknown error code");
1449             return;
1450         }
1451 
1452         /* If the error is masked, nothing to do here */
1453         if (!((1 << cxl_err_code) &
1454               ~ldl_le_p(reg_state + R_CXL_RAS_UNC_ERR_MASK))) {
1455             errors = errors->next;
1456             continue;
1457         }
1458 
1459         cxl_err = g_malloc0(sizeof(*cxl_err));
1460 
1461         cxl_err->type = cxl_err_code;
1462         while (header && header_count < 32) {
1463             cxl_err->header[header_count++] = header->value;
1464             header = header->next;
1465         }
1466         if (header_count > 32) {
1467             error_setg(errp, "Header must be 32 DWORD or less");
1468             return;
1469         }
1470         QTAILQ_INSERT_TAIL(&ct3d->error_list, cxl_err, node);
1471 
1472         errors = errors->next;
1473     }
1474 
1475     if (first && !QTAILQ_EMPTY(&ct3d->error_list)) {
1476         uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
1477         uint32_t capctrl = ldl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL);
1478         uint32_t *header_log = &cache_mem[R_CXL_RAS_ERR_HEADER0];
1479         int i;
1480 
1481         cxl_err = QTAILQ_FIRST(&ct3d->error_list);
1482         for (i = 0; i < CXL_RAS_ERR_HEADER_NUM; i++) {
1483             stl_le_p(header_log + i, cxl_err->header[i]);
1484         }
1485 
1486         capctrl = FIELD_DP32(capctrl, CXL_RAS_ERR_CAP_CTRL,
1487                              FIRST_ERROR_POINTER, cxl_err->type);
1488         stl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL, capctrl);
1489     }
1490 
1491     unc_err = 0;
1492     QTAILQ_FOREACH(cxl_err, &ct3d->error_list, node) {
1493         unc_err |= (1 << cxl_err->type);
1494     }
1495     if (!unc_err) {
1496         return;
1497     }
1498 
1499     stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_STATUS, unc_err);
1500     pcie_aer_inject_error(PCI_DEVICE(obj), &err);
1501 
1502     return;
1503 }
1504 
1505 void qmp_cxl_inject_correctable_error(const char *path, CxlCorErrorType type,
1506                                       Error **errp)
1507 {
1508     static PCIEAERErr err = {};
1509     Object *obj = object_resolve_path(path, NULL);
1510     CXLType3Dev *ct3d;
1511     uint32_t *reg_state;
1512     uint32_t cor_err;
1513     int cxl_err_type;
1514 
1515     if (!obj) {
1516         error_setg(errp, "Unable to resolve path");
1517         return;
1518     }
1519     if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1520         error_setg(errp, "Path does not point to a CXL type 3 device");
1521         return;
1522     }
1523 
1524     err.status = PCI_ERR_COR_INTERNAL;
1525     err.source_id = pci_requester_id(PCI_DEVICE(obj));
1526     err.flags = PCIE_AER_ERR_IS_CORRECTABLE;
1527 
1528     ct3d = CXL_TYPE3(obj);
1529     reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1530     cor_err = ldl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS);
1531 
1532     cxl_err_type = ct3d_qmp_cor_err_to_cxl(type);
1533     if (cxl_err_type < 0) {
1534         error_setg(errp, "Invalid COR error");
1535         return;
1536     }
1537     /* If the error is masked, nothting to do here */
1538     if (!((1 << cxl_err_type) &
1539           ~ldl_le_p(reg_state + R_CXL_RAS_COR_ERR_MASK))) {
1540         return;
1541     }
1542 
1543     cor_err |= (1 << cxl_err_type);
1544     stl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS, cor_err);
1545 
1546     pcie_aer_inject_error(PCI_DEVICE(obj), &err);
1547 }
1548 
1549 static void cxl_assign_event_header(CXLEventRecordHdr *hdr,
1550                                     const QemuUUID *uuid, uint32_t flags,
1551                                     uint8_t length, uint64_t timestamp)
1552 {
1553     st24_le_p(&hdr->flags, flags);
1554     hdr->length = length;
1555     memcpy(&hdr->id, uuid, sizeof(hdr->id));
1556     stq_le_p(&hdr->timestamp, timestamp);
1557 }
1558 
1559 static const QemuUUID gen_media_uuid = {
1560     .data = UUID(0xfbcd0a77, 0xc260, 0x417f,
1561                  0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6),
1562 };
1563 
1564 static const QemuUUID dram_uuid = {
1565     .data = UUID(0x601dcbb3, 0x9c06, 0x4eab, 0xb8, 0xaf,
1566                  0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24),
1567 };
1568 
1569 static const QemuUUID memory_module_uuid = {
1570     .data = UUID(0xfe927475, 0xdd59, 0x4339, 0xa5, 0x86,
1571                  0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74),
1572 };
1573 
1574 #define CXL_GMER_VALID_CHANNEL                          BIT(0)
1575 #define CXL_GMER_VALID_RANK                             BIT(1)
1576 #define CXL_GMER_VALID_DEVICE                           BIT(2)
1577 #define CXL_GMER_VALID_COMPONENT                        BIT(3)
1578 
1579 static int ct3d_qmp_cxl_event_log_enc(CxlEventLog log)
1580 {
1581     switch (log) {
1582     case CXL_EVENT_LOG_INFORMATIONAL:
1583         return CXL_EVENT_TYPE_INFO;
1584     case CXL_EVENT_LOG_WARNING:
1585         return CXL_EVENT_TYPE_WARN;
1586     case CXL_EVENT_LOG_FAILURE:
1587         return CXL_EVENT_TYPE_FAIL;
1588     case CXL_EVENT_LOG_FATAL:
1589         return CXL_EVENT_TYPE_FATAL;
1590     default:
1591         return -EINVAL;
1592     }
1593 }
1594 /* Component ID is device specific.  Define this as a string. */
1595 void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log,
1596                                         uint8_t flags, uint64_t dpa,
1597                                         uint8_t descriptor, uint8_t type,
1598                                         uint8_t transaction_type,
1599                                         bool has_channel, uint8_t channel,
1600                                         bool has_rank, uint8_t rank,
1601                                         bool has_device, uint32_t device,
1602                                         const char *component_id,
1603                                         Error **errp)
1604 {
1605     Object *obj = object_resolve_path(path, NULL);
1606     CXLEventGenMedia gem;
1607     CXLEventRecordHdr *hdr = &gem.hdr;
1608     CXLDeviceState *cxlds;
1609     CXLType3Dev *ct3d;
1610     uint16_t valid_flags = 0;
1611     uint8_t enc_log;
1612     int rc;
1613 
1614     if (!obj) {
1615         error_setg(errp, "Unable to resolve path");
1616         return;
1617     }
1618     if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1619         error_setg(errp, "Path does not point to a CXL type 3 device");
1620         return;
1621     }
1622     ct3d = CXL_TYPE3(obj);
1623     cxlds = &ct3d->cxl_dstate;
1624 
1625     rc = ct3d_qmp_cxl_event_log_enc(log);
1626     if (rc < 0) {
1627         error_setg(errp, "Unhandled error log type");
1628         return;
1629     }
1630     enc_log = rc;
1631 
1632     memset(&gem, 0, sizeof(gem));
1633     cxl_assign_event_header(hdr, &gen_media_uuid, flags, sizeof(gem),
1634                             cxl_device_get_timestamp(&ct3d->cxl_dstate));
1635 
1636     stq_le_p(&gem.phys_addr, dpa);
1637     gem.descriptor = descriptor;
1638     gem.type = type;
1639     gem.transaction_type = transaction_type;
1640 
1641     if (has_channel) {
1642         gem.channel = channel;
1643         valid_flags |= CXL_GMER_VALID_CHANNEL;
1644     }
1645 
1646     if (has_rank) {
1647         gem.rank = rank;
1648         valid_flags |= CXL_GMER_VALID_RANK;
1649     }
1650 
1651     if (has_device) {
1652         st24_le_p(gem.device, device);
1653         valid_flags |= CXL_GMER_VALID_DEVICE;
1654     }
1655 
1656     if (component_id) {
1657         strncpy((char *)gem.component_id, component_id,
1658                 sizeof(gem.component_id) - 1);
1659         valid_flags |= CXL_GMER_VALID_COMPONENT;
1660     }
1661 
1662     stw_le_p(&gem.validity_flags, valid_flags);
1663 
1664     if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&gem)) {
1665         cxl_event_irq_assert(ct3d);
1666     }
1667 }
1668 
1669 #define CXL_DRAM_VALID_CHANNEL                          BIT(0)
1670 #define CXL_DRAM_VALID_RANK                             BIT(1)
1671 #define CXL_DRAM_VALID_NIBBLE_MASK                      BIT(2)
1672 #define CXL_DRAM_VALID_BANK_GROUP                       BIT(3)
1673 #define CXL_DRAM_VALID_BANK                             BIT(4)
1674 #define CXL_DRAM_VALID_ROW                              BIT(5)
1675 #define CXL_DRAM_VALID_COLUMN                           BIT(6)
1676 #define CXL_DRAM_VALID_CORRECTION_MASK                  BIT(7)
1677 
1678 void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, uint8_t flags,
1679                                uint64_t dpa, uint8_t descriptor,
1680                                uint8_t type, uint8_t transaction_type,
1681                                bool has_channel, uint8_t channel,
1682                                bool has_rank, uint8_t rank,
1683                                bool has_nibble_mask, uint32_t nibble_mask,
1684                                bool has_bank_group, uint8_t bank_group,
1685                                bool has_bank, uint8_t bank,
1686                                bool has_row, uint32_t row,
1687                                bool has_column, uint16_t column,
1688                                bool has_correction_mask,
1689                                uint64List *correction_mask,
1690                                Error **errp)
1691 {
1692     Object *obj = object_resolve_path(path, NULL);
1693     CXLEventDram dram;
1694     CXLEventRecordHdr *hdr = &dram.hdr;
1695     CXLDeviceState *cxlds;
1696     CXLType3Dev *ct3d;
1697     uint16_t valid_flags = 0;
1698     uint8_t enc_log;
1699     int rc;
1700 
1701     if (!obj) {
1702         error_setg(errp, "Unable to resolve path");
1703         return;
1704     }
1705     if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1706         error_setg(errp, "Path does not point to a CXL type 3 device");
1707         return;
1708     }
1709     ct3d = CXL_TYPE3(obj);
1710     cxlds = &ct3d->cxl_dstate;
1711 
1712     rc = ct3d_qmp_cxl_event_log_enc(log);
1713     if (rc < 0) {
1714         error_setg(errp, "Unhandled error log type");
1715         return;
1716     }
1717     enc_log = rc;
1718 
1719     memset(&dram, 0, sizeof(dram));
1720     cxl_assign_event_header(hdr, &dram_uuid, flags, sizeof(dram),
1721                             cxl_device_get_timestamp(&ct3d->cxl_dstate));
1722     stq_le_p(&dram.phys_addr, dpa);
1723     dram.descriptor = descriptor;
1724     dram.type = type;
1725     dram.transaction_type = transaction_type;
1726 
1727     if (has_channel) {
1728         dram.channel = channel;
1729         valid_flags |= CXL_DRAM_VALID_CHANNEL;
1730     }
1731 
1732     if (has_rank) {
1733         dram.rank = rank;
1734         valid_flags |= CXL_DRAM_VALID_RANK;
1735     }
1736 
1737     if (has_nibble_mask) {
1738         st24_le_p(dram.nibble_mask, nibble_mask);
1739         valid_flags |= CXL_DRAM_VALID_NIBBLE_MASK;
1740     }
1741 
1742     if (has_bank_group) {
1743         dram.bank_group = bank_group;
1744         valid_flags |= CXL_DRAM_VALID_BANK_GROUP;
1745     }
1746 
1747     if (has_bank) {
1748         dram.bank = bank;
1749         valid_flags |= CXL_DRAM_VALID_BANK;
1750     }
1751 
1752     if (has_row) {
1753         st24_le_p(dram.row, row);
1754         valid_flags |= CXL_DRAM_VALID_ROW;
1755     }
1756 
1757     if (has_column) {
1758         stw_le_p(&dram.column, column);
1759         valid_flags |= CXL_DRAM_VALID_COLUMN;
1760     }
1761 
1762     if (has_correction_mask) {
1763         int count = 0;
1764         while (correction_mask && count < 4) {
1765             stq_le_p(&dram.correction_mask[count],
1766                      correction_mask->value);
1767             count++;
1768             correction_mask = correction_mask->next;
1769         }
1770         valid_flags |= CXL_DRAM_VALID_CORRECTION_MASK;
1771     }
1772 
1773     stw_le_p(&dram.validity_flags, valid_flags);
1774 
1775     if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&dram)) {
1776         cxl_event_irq_assert(ct3d);
1777     }
1778     return;
1779 }
1780 
1781 void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log,
1782                                         uint8_t flags, uint8_t type,
1783                                         uint8_t health_status,
1784                                         uint8_t media_status,
1785                                         uint8_t additional_status,
1786                                         uint8_t life_used,
1787                                         int16_t temperature,
1788                                         uint32_t dirty_shutdown_count,
1789                                         uint32_t corrected_volatile_error_count,
1790                                         uint32_t corrected_persist_error_count,
1791                                         Error **errp)
1792 {
1793     Object *obj = object_resolve_path(path, NULL);
1794     CXLEventMemoryModule module;
1795     CXLEventRecordHdr *hdr = &module.hdr;
1796     CXLDeviceState *cxlds;
1797     CXLType3Dev *ct3d;
1798     uint8_t enc_log;
1799     int rc;
1800 
1801     if (!obj) {
1802         error_setg(errp, "Unable to resolve path");
1803         return;
1804     }
1805     if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
1806         error_setg(errp, "Path does not point to a CXL type 3 device");
1807         return;
1808     }
1809     ct3d = CXL_TYPE3(obj);
1810     cxlds = &ct3d->cxl_dstate;
1811 
1812     rc = ct3d_qmp_cxl_event_log_enc(log);
1813     if (rc < 0) {
1814         error_setg(errp, "Unhandled error log type");
1815         return;
1816     }
1817     enc_log = rc;
1818 
1819     memset(&module, 0, sizeof(module));
1820     cxl_assign_event_header(hdr, &memory_module_uuid, flags, sizeof(module),
1821                             cxl_device_get_timestamp(&ct3d->cxl_dstate));
1822 
1823     module.type = type;
1824     module.health_status = health_status;
1825     module.media_status = media_status;
1826     module.additional_status = additional_status;
1827     module.life_used = life_used;
1828     stw_le_p(&module.temperature, temperature);
1829     stl_le_p(&module.dirty_shutdown_count, dirty_shutdown_count);
1830     stl_le_p(&module.corrected_volatile_error_count,
1831              corrected_volatile_error_count);
1832     stl_le_p(&module.corrected_persistent_error_count,
1833              corrected_persist_error_count);
1834 
1835     if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&module)) {
1836         cxl_event_irq_assert(ct3d);
1837     }
1838 }
1839 
1840 /* CXL r3.1 Table 8-50: Dynamic Capacity Event Record */
1841 static const QemuUUID dynamic_capacity_uuid = {
1842     .data = UUID(0xca95afa7, 0xf183, 0x4018, 0x8c, 0x2f,
1843                  0x95, 0x26, 0x8e, 0x10, 0x1a, 0x2a),
1844 };
1845 
1846 typedef enum CXLDCEventType {
1847     DC_EVENT_ADD_CAPACITY = 0x0,
1848     DC_EVENT_RELEASE_CAPACITY = 0x1,
1849     DC_EVENT_FORCED_RELEASE_CAPACITY = 0x2,
1850     DC_EVENT_REGION_CONFIG_UPDATED = 0x3,
1851     DC_EVENT_ADD_CAPACITY_RSP = 0x4,
1852     DC_EVENT_CAPACITY_RELEASED = 0x5,
1853 } CXLDCEventType;
1854 
1855 /*
1856  * Check whether the range [dpa, dpa + len - 1] has overlaps with extents in
1857  * the list.
1858  * Return value: return true if has overlaps; otherwise, return false
1859  */
1860 static bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list,
1861                                            uint64_t dpa, uint64_t len)
1862 {
1863     CXLDCExtent *ent;
1864     Range range1, range2;
1865 
1866     if (!list) {
1867         return false;
1868     }
1869 
1870     range_init_nofail(&range1, dpa, len);
1871     QTAILQ_FOREACH(ent, list, node) {
1872         range_init_nofail(&range2, ent->start_dpa, ent->len);
1873         if (range_overlaps_range(&range1, &range2)) {
1874             return true;
1875         }
1876     }
1877     return false;
1878 }
1879 
1880 /*
1881  * Check whether the range [dpa, dpa + len - 1] is contained by extents in
1882  * the list.
1883  * Will check multiple extents containment once superset release is added.
1884  * Return value: return true if range is contained; otherwise, return false
1885  */
1886 bool cxl_extents_contains_dpa_range(CXLDCExtentList *list,
1887                                     uint64_t dpa, uint64_t len)
1888 {
1889     CXLDCExtent *ent;
1890     Range range1, range2;
1891 
1892     if (!list) {
1893         return false;
1894     }
1895 
1896     range_init_nofail(&range1, dpa, len);
1897     QTAILQ_FOREACH(ent, list, node) {
1898         range_init_nofail(&range2, ent->start_dpa, ent->len);
1899         if (range_contains_range(&range2, &range1)) {
1900             return true;
1901         }
1902     }
1903     return false;
1904 }
1905 
1906 static bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list,
1907                                                  uint64_t dpa, uint64_t len)
1908 {
1909     CXLDCExtentGroup *group;
1910 
1911     if (!list) {
1912         return false;
1913     }
1914 
1915     QTAILQ_FOREACH(group, list, node) {
1916         if (cxl_extents_overlaps_dpa_range(&group->list, dpa, len)) {
1917             return true;
1918         }
1919     }
1920     return false;
1921 }
1922 
1923 /*
1924  * The main function to process dynamic capacity event with extent list.
1925  * Currently DC extents add/release requests are processed.
1926  */
1927 static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
1928         uint16_t hid, CXLDCEventType type, uint8_t rid,
1929         CxlDynamicCapacityExtentList *records, Error **errp)
1930 {
1931     Object *obj;
1932     CXLEventDynamicCapacity dCap = {};
1933     CXLEventRecordHdr *hdr = &dCap.hdr;
1934     CXLType3Dev *dcd;
1935     uint8_t flags = 1 << CXL_EVENT_TYPE_INFO;
1936     uint32_t num_extents = 0;
1937     CxlDynamicCapacityExtentList *list;
1938     CXLDCExtentGroup *group = NULL;
1939     g_autofree CXLDCExtentRaw *extents = NULL;
1940     uint8_t enc_log = CXL_EVENT_TYPE_DYNAMIC_CAP;
1941     uint64_t dpa, offset, len, block_size;
1942     g_autofree unsigned long *blk_bitmap = NULL;
1943     int i;
1944 
1945     obj = object_resolve_path_type(path, TYPE_CXL_TYPE3, NULL);
1946     if (!obj) {
1947         error_setg(errp, "Unable to resolve CXL type 3 device");
1948         return;
1949     }
1950 
1951     dcd = CXL_TYPE3(obj);
1952     if (!dcd->dc.num_regions) {
1953         error_setg(errp, "No dynamic capacity support from the device");
1954         return;
1955     }
1956 
1957 
1958     if (rid >= dcd->dc.num_regions) {
1959         error_setg(errp, "region id is too large");
1960         return;
1961     }
1962     block_size = dcd->dc.regions[rid].block_size;
1963     blk_bitmap = bitmap_new(dcd->dc.regions[rid].len / block_size);
1964 
1965     /* Sanity check and count the extents */
1966     list = records;
1967     while (list) {
1968         offset = list->value->offset;
1969         len = list->value->len;
1970         dpa = offset + dcd->dc.regions[rid].base;
1971 
1972         if (len == 0) {
1973             error_setg(errp, "extent with 0 length is not allowed");
1974             return;
1975         }
1976 
1977         if (offset % block_size || len % block_size) {
1978             error_setg(errp, "dpa or len is not aligned to region block size");
1979             return;
1980         }
1981 
1982         if (offset + len > dcd->dc.regions[rid].len) {
1983             error_setg(errp, "extent range is beyond the region end");
1984             return;
1985         }
1986 
1987         /* No duplicate or overlapped extents are allowed */
1988         if (test_any_bits_set(blk_bitmap, offset / block_size,
1989                               len / block_size)) {
1990             error_setg(errp, "duplicate or overlapped extents are detected");
1991             return;
1992         }
1993         bitmap_set(blk_bitmap, offset / block_size, len / block_size);
1994 
1995         if (type == DC_EVENT_RELEASE_CAPACITY) {
1996             if (cxl_extent_groups_overlaps_dpa_range(&dcd->dc.extents_pending,
1997                                                      dpa, len)) {
1998                 error_setg(errp,
1999                            "cannot release extent with pending DPA range");
2000                 return;
2001             }
2002             if (!ct3_test_region_block_backed(dcd, dpa, len)) {
2003                 error_setg(errp,
2004                            "cannot release extent with non-existing DPA range");
2005                 return;
2006             }
2007         } else if (type == DC_EVENT_ADD_CAPACITY) {
2008             if (cxl_extents_overlaps_dpa_range(&dcd->dc.extents, dpa, len)) {
2009                 error_setg(errp,
2010                            "cannot add DPA already accessible to the same LD");
2011                 return;
2012             }
2013             if (cxl_extent_groups_overlaps_dpa_range(&dcd->dc.extents_pending,
2014                                                      dpa, len)) {
2015                 error_setg(errp,
2016                            "cannot add DPA again while still pending");
2017                 return;
2018             }
2019         }
2020         list = list->next;
2021         num_extents++;
2022     }
2023 
2024     /* Create extent list for event being passed to host */
2025     i = 0;
2026     list = records;
2027     extents = g_new0(CXLDCExtentRaw, num_extents);
2028     while (list) {
2029         offset = list->value->offset;
2030         len = list->value->len;
2031         dpa = dcd->dc.regions[rid].base + offset;
2032 
2033         extents[i].start_dpa = dpa;
2034         extents[i].len = len;
2035         memset(extents[i].tag, 0, 0x10);
2036         extents[i].shared_seq = 0;
2037         if (type == DC_EVENT_ADD_CAPACITY) {
2038             group = cxl_insert_extent_to_extent_group(group,
2039                                                       extents[i].start_dpa,
2040                                                       extents[i].len,
2041                                                       extents[i].tag,
2042                                                       extents[i].shared_seq);
2043         }
2044 
2045         list = list->next;
2046         i++;
2047     }
2048     if (group) {
2049         cxl_extent_group_list_insert_tail(&dcd->dc.extents_pending, group);
2050     }
2051 
2052     /*
2053      * CXL r3.1 section 8.2.9.2.1.6: Dynamic Capacity Event Record
2054      *
2055      * All Dynamic Capacity event records shall set the Event Record Severity
2056      * field in the Common Event Record Format to Informational Event. All
2057      * Dynamic Capacity related events shall be logged in the Dynamic Capacity
2058      * Event Log.
2059      */
2060     cxl_assign_event_header(hdr, &dynamic_capacity_uuid, flags, sizeof(dCap),
2061                             cxl_device_get_timestamp(&dcd->cxl_dstate));
2062 
2063     dCap.type = type;
2064     /* FIXME: for now, validity flag is cleared */
2065     dCap.validity_flags = 0;
2066     stw_le_p(&dCap.host_id, hid);
2067     /* only valid for DC_REGION_CONFIG_UPDATED event */
2068     dCap.updated_region_id = 0;
2069     dCap.flags = 0;
2070     for (i = 0; i < num_extents; i++) {
2071         memcpy(&dCap.dynamic_capacity_extent, &extents[i],
2072                sizeof(CXLDCExtentRaw));
2073 
2074         if (i < num_extents - 1) {
2075             /* Set "More" flag */
2076             dCap.flags |= BIT(0);
2077         }
2078 
2079         if (cxl_event_insert(&dcd->cxl_dstate, enc_log,
2080                              (CXLEventRecordRaw *)&dCap)) {
2081             cxl_event_irq_assert(dcd);
2082         }
2083     }
2084 }
2085 
2086 void qmp_cxl_add_dynamic_capacity(const char *path, uint16_t host_id,
2087                                   CxlExtentSelectionPolicy sel_policy,
2088                                   uint8_t region, const char *tag,
2089                                   CxlDynamicCapacityExtentList  *extents,
2090                                   Error **errp)
2091 {
2092     switch (sel_policy) {
2093     case CXL_EXTENT_SELECTION_POLICY_PRESCRIPTIVE:
2094         qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id,
2095                                                       DC_EVENT_ADD_CAPACITY,
2096                                                       region, extents, errp);
2097         return;
2098     default:
2099         error_setg(errp, "Selection policy not supported");
2100         return;
2101     }
2102 }
2103 
2104 void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id,
2105                                       CxlExtentRemovalPolicy removal_policy,
2106                                       bool has_forced_removal,
2107                                       bool forced_removal,
2108                                       bool has_sanitize_on_release,
2109                                       bool sanitize_on_release,
2110                                       uint8_t region,
2111                                       const char *tag,
2112                                       CxlDynamicCapacityExtentList  *extents,
2113                                       Error **errp)
2114 {
2115     CXLDCEventType type = DC_EVENT_RELEASE_CAPACITY;
2116 
2117     if (has_forced_removal && forced_removal) {
2118         /* TODO: enable forced removal in the future */
2119         type = DC_EVENT_FORCED_RELEASE_CAPACITY;
2120         error_setg(errp, "Forced removal not supported yet");
2121         return;
2122     }
2123 
2124     switch (removal_policy) {
2125     case CXL_EXTENT_REMOVAL_POLICY_PRESCRIPTIVE:
2126         qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id, type,
2127                                                       region, extents, errp);
2128         return;
2129     default:
2130         error_setg(errp, "Removal policy not supported");
2131         return;
2132     }
2133 }
2134 
2135 static void ct3_class_init(ObjectClass *oc, void *data)
2136 {
2137     DeviceClass *dc = DEVICE_CLASS(oc);
2138     PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
2139     CXLType3Class *cvc = CXL_TYPE3_CLASS(oc);
2140 
2141     pc->realize = ct3_realize;
2142     pc->exit = ct3_exit;
2143     pc->class_id = PCI_CLASS_MEMORY_CXL;
2144     pc->vendor_id = PCI_VENDOR_ID_INTEL;
2145     pc->device_id = 0xd93; /* LVF for now */
2146     pc->revision = 1;
2147 
2148     pc->config_write = ct3d_config_write;
2149     pc->config_read = ct3d_config_read;
2150 
2151     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2152     dc->desc = "CXL Memory Device (Type 3)";
2153     device_class_set_legacy_reset(dc, ct3d_reset);
2154     device_class_set_props(dc, ct3_props);
2155 
2156     cvc->get_lsa_size = get_lsa_size;
2157     cvc->get_lsa = get_lsa;
2158     cvc->set_lsa = set_lsa;
2159     cvc->set_cacheline = set_cacheline;
2160 }
2161 
2162 static const TypeInfo ct3d_info = {
2163     .name = TYPE_CXL_TYPE3,
2164     .parent = TYPE_PCI_DEVICE,
2165     .class_size = sizeof(struct CXLType3Class),
2166     .class_init = ct3_class_init,
2167     .instance_size = sizeof(CXLType3Dev),
2168     .interfaces = (InterfaceInfo[]) {
2169         { INTERFACE_CXL_DEVICE },
2170         { INTERFACE_PCIE_DEVICE },
2171         {}
2172     },
2173 };
2174 
2175 static void ct3d_registers(void)
2176 {
2177     type_register_static(&ct3d_info);
2178 }
2179 
2180 type_init(ct3d_registers);
2181