@@ -4,6 +4,7 @@
#include "hw/mem/memory-device.h"
#include "hw/mem/pc-dimm.h"
#include "hw/pci/pci.h"
+#include "hw/pci/doe.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu/log.h"
@@ -11,6 +12,7 @@
#include "qemu/range.h"
#include "qemu/rcu.h"
#include "sysemu/hostmem.h"
+#include "sysemu/numa.h"
#include "hw/cxl/cxl.h"
typedef struct cxl_type3_dev {
@@ -21,6 +23,9 @@ typedef struct cxl_type3_dev {
uint64_t size;
HostMemoryBackend *hostmem;
+ PCIEDOE doe;
+ CXLCDAT cdat;
+
/* State */
CXLComponentState cxl_cstate;
CXLDeviceState cxl_dstate;
@@ -28,7 +33,7 @@ typedef struct cxl_type3_dev {
#define CT3(obj) OBJECT_CHECK(CXLType3Dev, (obj), TYPE_CXL_TYPE3_DEV)
-static void build_dvsecs(CXLType3Dev *ct3d)
+static int build_dvsecs(CXLType3Dev *ct3d)
{
CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
uint8_t *dvsec;
@@ -55,6 +60,7 @@ static void build_dvsecs(CXLType3Dev *ct3d)
};
cxl_component_create_dvsec(cxl_cstate, REG_LOC_DVSEC_LENGTH, REG_LOC_DVSEC,
REG_LOC_DVSEC_REVID, dvsec);
+ return cxl_cstate->dvsec_offset;
}
static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
@@ -201,6 +207,7 @@ 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;
+ int offset;
if (!ct3d->cxl_dstate.pmem) {
cxl_setup_memory(ct3d, errp);
@@ -213,7 +220,21 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
cxl_cstate->dvsec_offset = 0x100;
ct3d->cxl_cstate.pdev = pci_dev;
- build_dvsecs(ct3d);
+ offset = build_dvsecs(ct3d);
+
+ /* Build DOE - no interrupt for now */
+ offset = pcie_doe_ecap(&ct3d->doe, pci_dev, offset);
+ doe_add_message_handler(&ct3d->doe, 0x1e98, 0x2, &cxl_table_access,
+ &ct3d->cdat);
+
+ /* Store entires of CDAT for read back from DOE */
+ cdat_add_dsmas(&ct3d->cdat, 0, CDAT_DSMAS_FLAG_NV, 0x3345000000,
+ 0x0001000000);
+ cdat_add_dsmas(&ct3d->cdat, 1, 0, 0x33460000000, 0x00010000000);
+ cdat_add_dslbis(&ct3d->cdat, 0, HMAT_LB_MEM_MEMORY,
+ (uint8_t)HMAT_LB_DATA_ACCESS_LATENCY,
+ 1000, /* microsecs */
+ 90, 0, 0);
#ifndef SET_PMEM_PADDR
regs->special_ops = g_new0(MemoryRegionOps, 1);
@@ -287,6 +308,28 @@ static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,
info->type = MEMORY_DEVICE_INFO_KIND_CXL;
}
+static void ct3d_config_write(PCIDevice *pci_dev, uint32_t addr, uint32_t val, int len)
+{
+ CXLType3Dev *ct3d = CT3(pci_dev);
+
+ pci_default_write_config(pci_dev, addr, val, len);
+ pcie_doe_write(&ct3d->doe, addr, val, len);
+
+}
+
+static uint32_t ct3d_config_read(PCIDevice *pci_dev, uint32_t addr, int len)
+{
+ CXLType3Dev *ct3d = CT3(pci_dev);
+ int found = 0;
+ uint32_t val;
+
+ val = pcie_doe_read(&ct3d->doe, addr, len, &found);
+ if (found) {
+ return val;
+ }
+ return pci_default_read_config(pci_dev, addr, len);
+}
+
static void ct3_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -298,6 +341,8 @@ static void ct3_class_init(ObjectClass *oc, void *data)
pc->vendor_id = PCI_VENDOR_ID_INTEL;
pc->device_id = 0xd93; /* LVF for now */
pc->revision = 1;
+ pc->config_write = ct3d_config_write;
+ pc->config_read = ct3d_config_read;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->desc = "CXL PMEM Device (Type 3)";
@@ -13,6 +13,7 @@
#include "cxl_pci.h"
#include "cxl_component.h"
#include "cxl_device.h"
+#include "cxl_cdat.h"
#define COMPONENT_REG_BAR_IDX 0
#define DEVICE_REG_BAR_IDX 2
This enables basic read back of CDAT entries via a DOE mailbox in the devices PCI config space. Note that for now a few possible entries are provided that don't make a lot of sense for current instances of this device. It will need to be made somewhat dynamic and possibly require additional command line parameters. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> --- hw/mem/cxl_type3.c | 49 ++++++++++++++++++++++++++++++++++++++++++-- include/hw/cxl/cxl.h | 1 + 2 files changed, 48 insertions(+), 2 deletions(-)