[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v3 cxl-2.0-doe 2/2] CXL DOE support for CDAT and Compliance M
From: |
Chris Browy |
Subject: |
[RFC PATCH v3 cxl-2.0-doe 2/2] CXL DOE support for CDAT and Compliance Mode |
Date: |
Tue, 9 Mar 2021 16:04:36 -0500 |
---
hw/cxl/cxl-component-utils.c | 93 ++++++++++++
hw/mem/cxl_type3.c | 184 ++++++++++++++++++++++++
include/hw/cxl/cxl_cdat.h | 127 +++++++++++++++++
include/hw/cxl/cxl_compl.h | 252 +++++++++++++++++++++++++++++++++
include/hw/cxl/cxl_component.h | 74 ++++++++++
include/hw/cxl/cxl_device.h | 4 +
include/hw/cxl/cxl_pci.h | 2 +
7 files changed, 736 insertions(+)
create mode 100644 include/hw/cxl/cxl_cdat.h
create mode 100644 include/hw/cxl/cxl_compl.h
diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index 41d36f802a..1a2408dc76 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -11,6 +11,7 @@
#include "qemu/log.h"
#include "hw/pci/pci.h"
#include "hw/cxl/cxl.h"
+#include "qapi/error.h"
static uint64_t cxl_cache_mem_read_reg(void *opaque, hwaddr offset,
unsigned size)
@@ -206,3 +207,95 @@ void cxl_component_create_dvsec(CXLComponentState *cxl,
uint16_t length,
range_init_nofail(&cxl->dvsecs[type], cxl->dvsec_offset, length);
cxl->dvsec_offset += length;
}
+
+static void cdat_len_check(struct cdat_sub_header *hdr, Error **errp)
+{
+ assert(hdr->length);
+ assert(hdr->reserved == 0);
+
+ switch (hdr->type) {
+ case CDAT_TYPE_DSMAS:
+ assert(hdr->length == sizeof(struct cdat_dsmas));
+ break;
+ case CDAT_TYPE_DSLBIS:
+ assert(hdr->length == sizeof(struct cdat_dslbis));
+ break;
+ case CDAT_TYPE_DSMSCIS:
+ assert(hdr->length == sizeof(struct cdat_dsmscis));
+ break;
+ case CDAT_TYPE_DSIS:
+ assert(hdr->length == sizeof(struct cdat_dsis));
+ break;
+ case CDAT_TYPE_DSEMTS:
+ assert(hdr->length == sizeof(struct cdat_dsemts));
+ break;
+ case CDAT_TYPE_SSLBIS:
+ assert(hdr->length >= sizeof(struct cdat_sslbis_header));
+ assert((hdr->length - sizeof(struct cdat_sslbis_header)) %
+ sizeof(struct cdat_sslbe) == 0);
+ break;
+ default:
+ error_setg(errp, "Type %d is reserved", hdr->type);
+ }
+}
+
+#define IASL_HEADER_LEN 0x24
+void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp)
+{
+ uint8_t sum = 0;
+ int i, curr = 0, ent = 0;
+ CDATStruct cdat_st[1024];
+ struct cdat_sub_header hdr;
+ FILE *fp;
+ uint8_t iasl_hdr[IASL_HEADER_LEN];
+ size_t rcount;
+
+ fp = fopen(cxl_cstate->cdat_filename, "r");
+
+ if (fp) {
+ /* Read iASL header */
+ rcount= fread(&iasl_hdr, sizeof(iasl_hdr), 1, fp);
+ if (rcount == 0)
+ error_setg(errp, "File read failed");
+
+
+ for (i = 0; i < IASL_HEADER_LEN; i++) {
+ sum += iasl_hdr[i];
+ }
+ sum = (~sum + 1) & 0xFF;
+
+ curr = ftell(fp);
+
+ /* Read CDAT structures */
+ while (fread(&hdr, sizeof(hdr), 1, fp)) {
+ cdat_len_check(&hdr, errp);
+
+ cdat_st[ent].base2 = curr;
+ cdat_st[ent].length = hdr.length;
+ ent++;
+
+ fseek(fp, curr + hdr.length, SEEK_SET);
+ curr = ftell(fp);
+ }
+ /* Check the last structure */
+ fseek(fp, 0, SEEK_END);
+ assert(curr == ftell(fp));
+ } else {
+ error_setg(errp, "Please specify the CDAT file by using ',cdat='");
+ }
+ cxl_cstate->cdat_file = fp;
+
+ cxl_cstate->cdat_ent_len = ent;
+ cxl_cstate->cdat_ent = g_malloc0(sizeof(CDATStruct) * ent);
+ memcpy(cxl_cstate->cdat_ent, cdat_st, sizeof(CDATStruct) * ent);
+
+ /* Set CDAT header, ent = 0 */
+ cxl_cstate->cdat_header.revision = CXL_CDAT_REV;
+ cxl_cstate->cdat_header.sequence = 0;
+ cxl_cstate->cdat_header.length += curr + sizeof(cxl_cstate->cdat_header);
+
+ sum += cxl_cstate->cdat_header.revision +
+ cxl_cstate->cdat_header.sequence + cxl_cstate->cdat_header.length;
+
+ cxl_cstate->cdat_header.checksum = ~sum + 1;
+}
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index bf33ddb915..33f571e1a5 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -13,6 +13,156 @@
#include "qemu/rcu.h"
#include "sysemu/hostmem.h"
#include "hw/cxl/cxl.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+
+uint32_t cxl_doe_compliance_init(DOECap *doe_cap)
+{
+ CXLComponentState *cxl_cstate = &CT3(doe_cap->pdev)->cxl_cstate;
+ uint32_t req;
+ uint32_t byte_cnt = 0;
+
+ DOE_DBG(">> %s\n", __func__);
+
+ req = ((struct cxl_compliance_mode_cap *)pcie_doe_get_req(doe_cap))
+ ->req_header.req_code;
+ switch (req) {
+ case CXL_COMP_MODE_CAP:
+ byte_cnt = sizeof(struct cxl_compliance_mode_cap_rsp);
+ cxl_cstate->doe_resp.cap_rsp.header.vendor_id = CXL_VENDOR_ID;
+ cxl_cstate->doe_resp.cap_rsp.header.doe_type = CXL_DOE_COMPLIANCE;
+ cxl_cstate->doe_resp.cap_rsp.header.reserved = 0x0;
+ cxl_cstate->doe_resp.cap_rsp.header.length =
+ DIV_ROUND_UP(sizeof(struct cxl_compliance_mode_cap_rsp), 4);
+ cxl_cstate->doe_resp.cap_rsp.rsp_header.rsp_code = 0x0;
+ cxl_cstate->doe_resp.cap_rsp.rsp_header.version = 0x1;
+ cxl_cstate->doe_resp.cap_rsp.rsp_header.length = 0x1c;
+ cxl_cstate->doe_resp.cap_rsp.status = 0x0;
+ cxl_cstate->doe_resp.cap_rsp.available_cap_bitmask = 0x3;
+ cxl_cstate->doe_resp.cap_rsp.enabled_cap_bitmask = 0x3;
+ break;
+ case CXL_COMP_MODE_STATUS:
+ byte_cnt = sizeof(struct cxl_compliance_mode_status_rsp);
+ cxl_cstate->doe_resp.status_rsp.header.vendor_id = CXL_VENDOR_ID;
+ cxl_cstate->doe_resp.status_rsp.header.doe_type = CXL_DOE_COMPLIANCE;
+ cxl_cstate->doe_resp.status_rsp.header.reserved = 0x0;
+ cxl_cstate->doe_resp.status_rsp.header.length =
+ DIV_ROUND_UP(sizeof(struct cxl_compliance_mode_status_rsp), 4);
+ cxl_cstate->doe_resp.status_rsp.rsp_header.rsp_code = 0x1;
+ cxl_cstate->doe_resp.status_rsp.rsp_header.version = 0x1;
+ cxl_cstate->doe_resp.status_rsp.rsp_header.length = 0x14;
+ cxl_cstate->doe_resp.status_rsp.cap_bitfield = 0x3;
+ cxl_cstate->doe_resp.status_rsp.cache_size = 0;
+ cxl_cstate->doe_resp.status_rsp.cache_size_units = 0;
+ break;
+ default:
+ break;
+ }
+
+ DOE_DBG(" REQ=%x, RSP BYTE_CNT=%d\n", req, byte_cnt);
+ DOE_DBG("<< %s\n", __func__);
+ return byte_cnt;
+}
+
+
+bool cxl_doe_compliance_rsp(DOECap *doe_cap)
+{
+ CXLComponentState *cxl_cstate = &CT3(doe_cap->pdev)->cxl_cstate;
+ uint32_t byte_cnt;
+ uint32_t dw_cnt;
+
+ DOE_DBG(">> %s\n", __func__);
+
+ byte_cnt = cxl_doe_compliance_init(doe_cap);
+ dw_cnt = byte_cnt / 4;
+ memcpy(doe_cap->read_mbox,
+ cxl_cstate->doe_resp.data_byte, byte_cnt);
+
+ doe_cap->read_mbox_len += dw_cnt;
+
+ DOE_DBG(" LEN=%x, RD MBOX[%d]=%x\n", dw_cnt - 1,
+ doe_cap->read_mbox_len,
+ *(doe_cap->read_mbox + dw_cnt - 1));
+
+ DOE_DBG("<< %s\n", __func__);
+
+ return true;
+}
+
+bool cxl_doe_cdat_rsp(DOECap *doe_cap)
+{
+ CXLComponentState *cxl_cstate = &CT3(doe_cap->pdev)->cxl_cstate;
+ uint16_t ent;
+ uint32_t base = 0;
+ uint32_t len = 0 ;
+ size_t rcount;
+ struct cxl_cdat *req = pcie_doe_get_req(doe_cap);
+
+ ent = req->entry_handle;
+ if (ent == 0) {
+ len = sizeof(cxl_cstate->cdat_header);
+ } else if (ent <= cxl_cstate->cdat_ent_len) {
+ base = cxl_cstate->cdat_ent[ent - 1].base2;
+ len = cxl_cstate->cdat_ent[ent - 1].length;
+ }
+
+ struct cxl_cdat_rsp rsp = {
+ .header = {
+ .vendor_id = CXL_VENDOR_ID,
+ .doe_type = CXL_DOE_TABLE_ACCESS,
+ .reserved = 0x0,
+ .length = (sizeof(struct cxl_cdat_rsp) + len) / 4,
+ },
+ .req_code = CXL_DOE_TAB_RSP,
+ .table_type = CXL_DOE_TAB_TYPE_CDAT,
+ .entry_handle = (ent < cxl_cstate->cdat_ent_len) ? ent + 1 :
CXL_DOE_TAB_ENT_MAX,
+ };
+
+ memcpy(doe_cap->read_mbox, &rsp, sizeof(rsp));
+
+ if (ent == 0) {
+ memcpy(doe_cap->read_mbox + sizeof(rsp) / 4,
+ &cxl_cstate->cdat_header, len);
+ } else if (ent <= cxl_cstate->cdat_ent_len) {
+ fseek(cxl_cstate->cdat_file, base, SEEK_SET);
+ rcount= fread(doe_cap->read_mbox + sizeof(rsp) / 4, len, 1,
cxl_cstate->cdat_file);
+ if (rcount == 0)
+ DOE_DBG("fread returned 0\n");
+ }
+
+ doe_cap->read_mbox_len += rsp.header.length;
+ DOE_DBG("%s: INCR RD_MBOX OFF=%x\n", __func__, doe_cap->read_mbox_len);
+
+ for (int i = 0; i < doe_cap->read_mbox_len; i++) {
+ DOE_DBG(" RD_MBOX[%d]=%08x\n", i, doe_cap->read_mbox[i]);
+ }
+
+ return true;
+}
+
+static uint32_t ct3d_config_read(PCIDevice *pci_dev, uint32_t addr, int size)
+{
+ CXLType3Dev *ct3d = CT3(pci_dev);
+ uint32_t val;
+
+ if (pcie_doe_read_config(&ct3d->doe_comp, addr, size, &val)) {
+ return val;
+ } else if (pcie_doe_read_config(&ct3d->doe_cdat, addr, size, &val)) {
+ return val;
+ }
+
+ return pci_default_read_config(pci_dev, addr, size);
+}
+
+static void ct3d_config_write(PCIDevice *pci_dev, uint32_t addr, uint32_t val,
+ int size)
+{
+ CXLType3Dev *ct3d = CT3(pci_dev);
+
+ pcie_doe_write_config(&ct3d->doe_comp, addr, val, size);
+ pcie_doe_write_config(&ct3d->doe_cdat, addr, val, size);
+ pci_default_write_config(pci_dev, addr, val, size);
+}
static void build_dvsecs(CXLType3Dev *ct3d)
{
@@ -134,6 +284,8 @@ static void ct3_finalize(Object *obj)
g_free((void *)regs->special_ops);
g_free(ct3d->cxl_dstate.pmem);
+
+ fclose(cxl_cstate->cdat_file);
}
static void cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
@@ -203,6 +355,19 @@ static MemoryRegion
*cxl_md_get_memory_region(MemoryDeviceState *md,
return ct3d->cxl_dstate.pmem;
}
+static DOEProtocol doe_comp_prot[] = {
+ {PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_CMA, pcie_doe_cma_rsp},
+ {CXL_VENDOR_ID, CXL_DOE_COMPLIANCE, cxl_doe_compliance_rsp},
+ {CXL_VENDOR_ID, CXL_DOE_TABLE_ACCESS, cxl_doe_cdat_rsp},
+ { /* End of array */ },
+};
+
+static DOEProtocol doe_cdat_prot[] = {
+ {PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_CMA, pcie_doe_cma_rsp},
+ {CXL_VENDOR_ID, CXL_DOE_TABLE_ACCESS, cxl_doe_cdat_rsp},
+ { /* End of array */ },
+};
+
static void ct3_realize(PCIDevice *pci_dev, Error **errp)
{
CXLType3Dev *ct3d = CT3(pci_dev);
@@ -210,6 +375,8 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
ComponentRegisters *regs = &cxl_cstate->crb;
MemoryRegion *mr = ®s->component_registers;
uint8_t *pci_conf = pci_dev->config;
+ unsigned short msix_num = 2;
+ int i;
if (!ct3d->cxl_dstate.pmem) {
cxl_setup_memory(ct3d, errp);
@@ -239,6 +406,19 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_64,
&ct3d->cxl_dstate.device_registers);
+
+ /* MSI(-X) Initailization */
+ msix_init_exclusive_bar(pci_dev, msix_num, 4, NULL);
+ for (i = 0; i < msix_num; i++) {
+ msix_vector_use(pci_dev, i);
+ }
+ /* msi_init(pci_dev, 0x60, 16, true, false, NULL); */
+
+ /* DOE Initailization */
+ pcie_doe_init(pci_dev, &ct3d->doe_comp, 0x160, doe_comp_prot, true, 0);
+ pcie_doe_init(pci_dev, &ct3d->doe_cdat, 0x190, doe_cdat_prot, true, 1);
+
+ cxl_doe_cdat_init(cxl_cstate, errp);
}
static uint64_t cxl_md_get_addr(const MemoryDeviceState *md)
@@ -275,6 +455,7 @@ static Property ct3_props[] = {
HostMemoryBackend *),
DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND,
HostMemoryBackend *),
+ DEFINE_PROP_STRING("cdat", CXLType3Dev, cxl_cstate.cdat_filename),
DEFINE_PROP_END_OF_LIST(),
};
@@ -357,6 +538,9 @@ static void ct3_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc);
+
+ pc->config_write = ct3d_config_write;
+ pc->config_read = ct3d_config_read;
CXLType3Class *cvc = CXL_TYPE3_DEV_CLASS(oc);
pc->realize = ct3_realize;
diff --git a/include/hw/cxl/cxl_cdat.h b/include/hw/cxl/cxl_cdat.h
new file mode 100644
index 0000000000..edd994d410
--- /dev/null
+++ b/include/hw/cxl/cxl_cdat.h
@@ -0,0 +1,127 @@
+/*
+ * CXL CDAT Structure
+ *
+ * Copyright (C) 2020 Avery Design Systems, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_CDAT_H
+#define CXL_CDAT_H
+
+#include "hw/cxl/cxl_pci.h"
+
+#define CXL_DOE_TABLE_ACCESS 2
+#define CXL_DOE_PROTOCOL_CDAT ((CXL_DOE_TABLE_ACCESS << 16) |
CXL_VENDOR_ID)
+
+/*
+ * DOE CDAT Table Protocol (CXL Spec)
+ */
+#define CXL_DOE_TAB_REQ 0
+#define CXL_DOE_TAB_RSP 0
+#define CXL_DOE_TAB_TYPE_CDAT 0
+#define CXL_DOE_TAB_ENT_MAX 0xFFFF
+
+/* Read Entry Request, 8.1.11.1 Table 134 */
+struct cxl_cdat {
+ DOEHeader header;
+ uint8_t req_code;
+ uint8_t table_type;
+ uint16_t entry_handle;
+} QEMU_PACKED;
+
+/* Read Entry Response, 8.1.11.1 Table 135 */
+#define cxl_cdat_rsp cxl_cdat /* Same as request */
+
+/*
+ * CDAT Table Structure (CDAT Spec)
+ */
+#define CXL_CDAT_REV 1
+
+/* Data object header */
+struct cdat_table_header {
+ uint32_t length; /* Length of table in bytes, including this header */
+ uint8_t revision; /* ACPI Specification minor version number */
+ uint8_t checksum; /* To make sum of entire table == 0 */
+ uint8_t reserved[6];
+ uint32_t sequence; /* ASCII table signature */
+} QEMU_PACKED;
+
+/* Values for subtable type in CDAT structures */
+enum cdat_type {
+ CDAT_TYPE_DSMAS = 0,
+ CDAT_TYPE_DSLBIS = 1,
+ CDAT_TYPE_DSMSCIS = 2,
+ CDAT_TYPE_DSIS = 3,
+ CDAT_TYPE_DSEMTS = 4,
+ CDAT_TYPE_SSLBIS = 5,
+ CDAT_TYPE_MAX
+};
+
+struct cdat_sub_header {
+ uint8_t type;
+ uint8_t reserved;
+ uint16_t length;
+};
+
+/* CDAT Structure Subtables */
+struct cdat_dsmas {
+ struct cdat_sub_header header;
+ uint8_t DSMADhandle;
+ uint8_t flags;
+ uint16_t reserved;
+ uint64_t DPA_base;
+ uint64_t DPA_length;
+} QEMU_PACKED;
+
+struct cdat_dslbis {
+ struct cdat_sub_header header;
+ uint8_t handle;
+ uint8_t flags;
+ uint8_t data_type;
+ uint8_t reserved;
+ uint64_t entry_base_unit;
+ uint16_t entry[3];
+ uint16_t reserved2;
+} QEMU_PACKED;
+
+struct cdat_dsmscis {
+ struct cdat_sub_header header;
+ uint8_t DSMAS_handle;
+ uint8_t reserved[3];
+ uint64_t memory_side_cache_size;
+ uint32_t cache_attributes;
+} QEMU_PACKED;
+
+struct cdat_dsis {
+ struct cdat_sub_header header;
+ uint8_t flags;
+ uint8_t handle;
+ uint16_t reserved;
+} QEMU_PACKED;
+
+struct cdat_dsemts {
+ struct cdat_sub_header header;
+ uint8_t DSMAS_handle;
+ uint8_t EFI_memory_type_attr;
+ uint16_t reserved;
+ uint64_t DPA_offset;
+ uint64_t DPA_length;
+} QEMU_PACKED;
+
+struct cdat_sslbe {
+ uint16_t port_x_id;
+ uint16_t port_y_id;
+ uint16_t latency_bandwidth;
+ uint16_t reserved;
+} QEMU_PACKED;
+
+struct cdat_sslbis_header {
+ struct cdat_sub_header header;
+ uint8_t data_type;
+ uint8_t reserved[3];
+ uint64_t entry_base_unit;
+} QEMU_PACKED;
+
+#endif /* CXL_CDAT_H */
diff --git a/include/hw/cxl/cxl_compl.h b/include/hw/cxl/cxl_compl.h
new file mode 100644
index 0000000000..5edeaa5f27
--- /dev/null
+++ b/include/hw/cxl/cxl_compl.h
@@ -0,0 +1,252 @@
+/*
+ * CXL Compliance Structure
+ *
+ * Copyright (C) 2020 Avery Design Systems, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_COMPL_H
+#define CXL_COMPL_H
+
+#include "hw/cxl/cxl_pci.h"
+
+#define CXL_DOE_COMPLIANCE 0
+#define CXL_DOE_PROTOCOL_COMPLIANCE ((CXL_DOE_COMPLIANCE << 16) |
CXL_VENDOR_ID)
+
+/* 14.16.4 - Compliance Mode */
+#define CXL_COMP_MODE_CAP 0x0
+#define CXL_COMP_MODE_STATUS 0x1
+#define CXL_COMP_MODE_HALT 0x2
+#define CXL_COMP_MODE_MULT_WR_STREAM 0x3
+#define CXL_COMP_MODE_PRO_CON 0x4
+#define CXL_COMP_MODE_BOGUS 0x5
+#define CXL_COMP_MODE_INJ_POISON 0x6
+#define CXL_COMP_MODE_INJ_CRC 0x7
+#define CXL_COMP_MODE_INJ_FC 0x8
+#define CXL_COMP_MODE_TOGGLE_CACHE 0x9
+#define CXL_COMP_MODE_INJ_MAC 0xa
+#define CXL_COMP_MODE_INS_UNEXP_MAC 0xb
+#define CXL_COMP_MODE_INJ_VIRAL 0xc
+#define CXL_COMP_MODE_INJ_ALMP 0xd
+#define CXL_COMP_MODE_IGN_ALMP 0xe
+
+typedef struct compliance_req_header CompReqHeader;
+typedef struct compliance_rsp_header CompRspHeader;
+
+struct compliance_req_header {
+ uint8_t req_code;
+ uint8_t version;
+ uint16_t reserved;
+} QEMU_PACKED;
+
+struct compliance_rsp_header {
+ uint8_t rsp_code;
+ uint8_t version;
+ uint8_t length;
+} QEMU_PACKED;
+
+struct status_rsp {
+ DOEHeader header;
+ CompRspHeader rsp_header;
+ uint8_t status;
+} QEMU_PACKED;
+
+struct len_rsvd_rsp {
+ DOEHeader header;
+ /* The length field in rsp_header is reserved. */
+ CompRspHeader rsp_header;
+ uint8_t reserved[5];
+} QEMU_PACKED;
+
+/*
+ * CXL Compliance Mode Protocol 14.16.4
+ */
+/* 14.16.4.1 */
+struct cxl_compliance_mode_cap {
+ DOEHeader header;
+ CompReqHeader req_header;
+} QEMU_PACKED;
+
+struct cxl_compliance_mode_cap_rsp {
+ DOEHeader header;
+ CompRspHeader rsp_header;
+ uint8_t status;
+ uint64_t available_cap_bitmask;
+ uint64_t enabled_cap_bitmask;
+} QEMU_PACKED;
+
+/* 14.16.4.2 */
+struct cxl_compliance_mode_status {
+ DOEHeader header;
+ CompReqHeader req_header;
+} QEMU_PACKED;
+
+struct cxl_compliance_mode_status_rsp {
+ DOEHeader header;
+ CompRspHeader rsp_header;
+ uint32_t cap_bitfield;
+ uint16_t cache_size;
+ uint8_t cache_size_units;
+} QEMU_PACKED;
+
+/* 14.16.4.3 */
+struct cxl_compliance_mode_halt {
+ DOEHeader header;
+ CompReqHeader req_header;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_halt_rsp status_rsp
+
+/* 14.16.4.4 */
+struct cxl_compliance_mode_multiple_write_streaming {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t protocol;
+ uint8_t virtual_addr;
+ uint8_t self_checking;
+ uint8_t verify_read_semantics;
+ uint8_t num_inc;
+ uint8_t num_sets;
+ uint8_t num_loops;
+ uint8_t reserved2;
+ uint64_t start_addr;
+ uint64_t write_addr;
+ uint64_t writeback_addr;
+ uint64_t byte_mask;
+ uint32_t addr_incr;
+ uint32_t set_offset;
+ uint32_t pattern_p;
+ uint32_t inc_pattern_b;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_multiple_write_streaming_rsp status_rsp
+
+/* 14.16.4.5 */
+struct cxl_compliance_mode_producer_consumer {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t protocol;
+ uint8_t num_inc;
+ uint8_t num_sets;
+ uint8_t num_loops;
+ uint8_t write_semantics;
+ uint8_t reserved2[3];
+ uint64_t start_addr;
+ uint64_t byte_mask;
+ uint32_t addr_incr;
+ uint32_t set_offset;
+ uint32_t pattern;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_producer_consumer_rsp status_rsp
+
+/* 14.16.4.6 */
+struct cxl_compliance_mode_inject_bogus_writes {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t count;
+ uint8_t reserved;
+ uint32_t pattern;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_bogus_writes_rsp status_rsp
+
+/* 14.16.4.7 */
+struct cxl_compliance_mode_inject_poison {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t protocol;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_poison_rsp status_rsp
+
+/* 14.16.4.8 */
+struct cxl_compliance_mode_inject_crc {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t num_bits_flip;
+ uint8_t num_flits_inj;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_crc_rsp status_rsp
+
+/* 14.16.4.9 */
+struct cxl_compliance_mode_inject_flow_control {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t inj_flow_control;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_flow_control_rsp status_rsp
+
+/* 14.16.4.10 */
+struct cxl_compliance_mode_toggle_cache_flush {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t inj_flow_control;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_toggle_cache_flush_rsp status_rsp
+
+/* 14.16.4.11 */
+struct cxl_compliance_mode_inject_mac_delay {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t enable;
+ uint8_t mode;
+ uint8_t delay;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_mac_delay_rsp status_rsp
+
+/* 14.16.4.12 */
+struct cxl_compliance_mode_insert_unexp_mac {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t opcode;
+ uint8_t mode;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_insert_unexp_mac_rsp status_rsp
+
+/* 14.16.4.13 */
+struct cxl_compliance_mode_inject_viral {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t protocol;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_viral_rsp status_rsp
+
+/* 14.16.4.14 */
+struct cxl_compliance_mode_inject_almp {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t opcode;
+ uint8_t reserved2[3];
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_almp_rsp len_rsvd_rsp
+
+/* 14.16.4.15 */
+struct cxl_compliance_mode_ignore_almp {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t opcode;
+ uint8_t reserved2[3];
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_ignore_almp_rsp len_rsvd_rsp
+
+/* 14.16.4.16 */
+struct cxl_compliance_mode_inject_bit_error {
+ DOEHeader header;
+ CompReqHeader req_header;
+ uint8_t opcode;
+} QEMU_PACKED;
+
+#define cxl_compliance_mode_inject_bit_error_rsp len_rsvd_rsp
+
+#endif /* CXL_COMPL_H */
diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
index acc0730d96..1294d74d78 100644
--- a/include/hw/cxl/cxl_component.h
+++ b/include/hw/cxl/cxl_component.h
@@ -18,6 +18,7 @@
#include "qemu/range.h"
#include "qemu/typedefs.h"
#include "hw/register.h"
+#include "qapi/error.h"
enum reg_type {
CXL2_DEVICE,
@@ -160,6 +161,11 @@ typedef struct component_registers {
MemoryRegionOps *special_ops;
} ComponentRegisters;
+typedef struct cdat_struct {
+ void *base;
+ uint32_t base2;
+ uint32_t length;
+} CDATStruct;
/*
* A CXL component represents all entities in a CXL hierarchy. This includes,
* host bridges, root ports, upstream/downstream switch ports, and devices
@@ -173,6 +179,70 @@ typedef struct cxl_component {
struct PCIDevice *pdev;
};
};
+
+ /*
+ * SW write write mailbox and GO on last DW
+ * device sets READY of offset DW in DO types to copy
+ * to read mailbox register on subsequent cfg_read
+ * of read mailbox register and then on cfg_write to
+ * denote success read increments offset to next DW
+ */
+
+ union doe_request_u {
+ /* Compliance DOE Data Objects Type=0*/
+ struct cxl_compliance_mode_cap mode_cap;
+ struct cxl_compliance_mode_status mode_status;
+ struct cxl_compliance_mode_halt mode_halt;
+ struct cxl_compliance_mode_multiple_write_streaming
+ multiple_write_streaming;
+ struct cxl_compliance_mode_producer_consumer producer_consumer;
+ struct cxl_compliance_mode_inject_bogus_writes inject_bogus_writes;
+ struct cxl_compliance_mode_inject_poison inject_poison;
+ struct cxl_compliance_mode_inject_crc inject_crc;
+ struct cxl_compliance_mode_inject_flow_control inject_flow_control;
+ struct cxl_compliance_mode_toggle_cache_flush toggle_cache_flush;
+ struct cxl_compliance_mode_inject_mac_delay inject_mac_delay;
+ struct cxl_compliance_mode_insert_unexp_mac insert_unexp_mac;
+ struct cxl_compliance_mode_inject_viral inject_viral;
+ struct cxl_compliance_mode_inject_almp inject_almp;
+ struct cxl_compliance_mode_ignore_almp ignore_almp;
+ struct cxl_compliance_mode_inject_bit_error ignore_bit_error;
+ char data_byte[128];
+ } doe_request;
+
+ union doe_resp_u {
+ /* Compliance DOE Data Objects Type=0*/
+ struct cxl_compliance_mode_cap_rsp cap_rsp;
+ struct cxl_compliance_mode_status_rsp status_rsp;
+ struct cxl_compliance_mode_halt_rsp halt_rsp;
+ struct cxl_compliance_mode_multiple_write_streaming_rsp
+ multiple_write_streaming_rsp;
+ struct cxl_compliance_mode_producer_consumer_rsp producer_consumer_rsp;
+ struct cxl_compliance_mode_inject_bogus_writes_rsp
+ inject_bogus_writes_rsp;
+ struct cxl_compliance_mode_inject_poison_rsp inject_poison_rsp;
+ struct cxl_compliance_mode_inject_crc_rsp inject_crc_rsp;
+ struct cxl_compliance_mode_inject_flow_control_rsp
+ inject_flow_control_rsp;
+ struct cxl_compliance_mode_toggle_cache_flush_rsp
+ toggle_cache_flush_rsp;
+ struct cxl_compliance_mode_inject_mac_delay_rsp inject_mac_delay_rsp;
+ struct cxl_compliance_mode_insert_unexp_mac_rsp insert_unexp_mac_rsp;
+ struct cxl_compliance_mode_inject_viral inject_viral_rsp;
+ struct cxl_compliance_mode_inject_almp_rsp inject_almp_rsp;
+ struct cxl_compliance_mode_ignore_almp_rsp ignore_almp_rsp;
+ struct cxl_compliance_mode_inject_bit_error_rsp ignore_bit_error_rsp;
+ char data_byte[520 * 4];
+ } doe_resp;
+
+ /* Table entry types */
+ struct cdat_table_header cdat_header;
+
+ CDATStruct *cdat_ent;
+ int cdat_ent_len;
+
+ char *cdat_filename;
+ FILE *cdat_file;
} CXLComponentState;
void cxl_component_register_block_init(Object *obj,
@@ -184,4 +254,8 @@ void cxl_component_register_init_common(uint32_t *reg_state,
void cxl_component_create_dvsec(CXLComponentState *cxl_cstate, uint16_t length,
uint16_t type, uint8_t rev, uint8_t *body);
+uint32_t cxl_doe_compliance_init(DOECap *doe_cap);
+bool cxl_doe_compliance_rsp(DOECap *doe_cap);
+void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
+bool cxl_doe_cdat_rsp(DOECap *doe_cap);
#endif
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 057c5b85c6..de006ff463 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -236,6 +236,10 @@ typedef struct cxl_type3_dev {
/* State */
CXLComponentState cxl_cstate;
CXLDeviceState cxl_dstate;
+
+ /* DOE */
+ DOECap doe_comp;
+ DOECap doe_cdat;
} CXLType3Dev;
#ifndef TYPE_CXL_TYPE3_DEV
diff --git a/include/hw/cxl/cxl_pci.h b/include/hw/cxl/cxl_pci.h
index e8235b10cc..a0df324a1f 100644
--- a/include/hw/cxl/cxl_pci.h
+++ b/include/hw/cxl/cxl_pci.h
@@ -12,6 +12,8 @@
#include "hw/pci/pci.h"
#include "hw/pci/pcie.h"
+#include "hw/cxl/cxl_cdat.h"
+#include "hw/cxl/cxl_compl.h"
#define CXL_VENDOR_ID 0x1e98
--
2.17.1