hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qemu/units.h"
|
|
|
|
#include "qemu/error-report.h"
|
|
|
|
#include "hw/mem/memory-device.h"
|
|
|
|
#include "hw/mem/pc-dimm.h"
|
|
|
|
#include "hw/pci/pci.h"
|
|
|
|
#include "hw/qdev-properties.h"
|
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "qemu/log.h"
|
|
|
|
#include "qemu/module.h"
|
2022-04-29 16:40:46 +02:00
|
|
|
#include "qemu/pmem.h"
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
#include "qemu/range.h"
|
|
|
|
#include "qemu/rcu.h"
|
|
|
|
#include "sysemu/hostmem.h"
|
|
|
|
#include "hw/cxl/cxl.h"
|
|
|
|
|
|
|
|
static void build_dvsecs(CXLType3Dev *ct3d)
|
|
|
|
{
|
|
|
|
CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
|
|
|
|
uint8_t *dvsec;
|
|
|
|
|
|
|
|
dvsec = (uint8_t *)&(CXLDVSECDevice){
|
|
|
|
.cap = 0x1e,
|
|
|
|
.ctrl = 0x2,
|
|
|
|
.status2 = 0x2,
|
|
|
|
.range1_size_hi = ct3d->hostmem->size >> 32,
|
|
|
|
.range1_size_lo = (2 << 5) | (2 << 2) | 0x3 |
|
|
|
|
(ct3d->hostmem->size & 0xF0000000),
|
|
|
|
.range1_base_hi = 0,
|
|
|
|
.range1_base_lo = 0,
|
|
|
|
};
|
|
|
|
cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
|
|
|
|
PCIE_CXL_DEVICE_DVSEC_LENGTH,
|
|
|
|
PCIE_CXL_DEVICE_DVSEC,
|
|
|
|
PCIE_CXL2_DEVICE_DVSEC_REVID, dvsec);
|
|
|
|
|
|
|
|
dvsec = (uint8_t *)&(CXLDVSECRegisterLocator){
|
|
|
|
.rsvd = 0,
|
|
|
|
.reg0_base_lo = RBI_COMPONENT_REG | CXL_COMPONENT_REG_BAR_IDX,
|
|
|
|
.reg0_base_hi = 0,
|
|
|
|
.reg1_base_lo = RBI_CXL_DEVICE_REG | CXL_DEVICE_REG_BAR_IDX,
|
|
|
|
.reg1_base_hi = 0,
|
|
|
|
};
|
|
|
|
cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
|
|
|
|
REG_LOC_DVSEC_LENGTH, REG_LOC_DVSEC,
|
|
|
|
REG_LOC_DVSEC_REVID, dvsec);
|
|
|
|
dvsec = (uint8_t *)&(CXLDVSECDeviceGPF){
|
|
|
|
.phase2_duration = 0x603, /* 3 seconds */
|
|
|
|
.phase2_power = 0x33, /* 0x33 miliwatts */
|
|
|
|
};
|
|
|
|
cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
|
|
|
|
GPF_DEVICE_DVSEC_LENGTH, GPF_PORT_DVSEC,
|
|
|
|
GPF_DEVICE_DVSEC_REVID, dvsec);
|
|
|
|
}
|
|
|
|
|
2022-04-29 16:40:43 +02:00
|
|
|
static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
|
|
|
|
{
|
|
|
|
ComponentRegisters *cregs = &ct3d->cxl_cstate.crb;
|
|
|
|
uint32_t *cache_mem = cregs->cache_mem_registers;
|
|
|
|
|
|
|
|
assert(which == 0);
|
|
|
|
|
|
|
|
/* TODO: Sanity checks that the decoder is possible */
|
|
|
|
ARRAY_FIELD_DP32(cache_mem, CXL_HDM_DECODER0_CTRL, COMMIT, 0);
|
|
|
|
ARRAY_FIELD_DP32(cache_mem, CXL_HDM_DECODER0_CTRL, ERR, 0);
|
|
|
|
|
|
|
|
ARRAY_FIELD_DP32(cache_mem, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ct3d_reg_write(void *opaque, hwaddr offset, uint64_t value,
|
|
|
|
unsigned size)
|
|
|
|
{
|
|
|
|
CXLComponentState *cxl_cstate = opaque;
|
|
|
|
ComponentRegisters *cregs = &cxl_cstate->crb;
|
|
|
|
CXLType3Dev *ct3d = container_of(cxl_cstate, CXLType3Dev, cxl_cstate);
|
|
|
|
uint32_t *cache_mem = cregs->cache_mem_registers;
|
|
|
|
bool should_commit = false;
|
|
|
|
int which_hdm = -1;
|
|
|
|
|
|
|
|
assert(size == 4);
|
|
|
|
g_assert(offset < CXL2_COMPONENT_CM_REGION_SIZE);
|
|
|
|
|
|
|
|
switch (offset) {
|
|
|
|
case A_CXL_HDM_DECODER0_CTRL:
|
|
|
|
should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
|
|
|
|
which_hdm = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
stl_le_p((uint8_t *)cache_mem + offset, value);
|
|
|
|
if (should_commit) {
|
|
|
|
hdm_decoder_commit(ct3d, which_hdm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
|
|
|
|
{
|
2022-04-29 16:40:57 +02:00
|
|
|
DeviceState *ds = DEVICE(ct3d);
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
MemoryRegion *mr;
|
2022-04-29 16:40:57 +02:00
|
|
|
char *name;
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
|
|
|
|
if (!ct3d->hostmem) {
|
|
|
|
error_setg(errp, "memdev property must be set");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mr = host_memory_backend_get_memory(ct3d->hostmem);
|
|
|
|
if (!mr) {
|
|
|
|
error_setg(errp, "memdev property must be set");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
memory_region_set_nonvolatile(mr, true);
|
|
|
|
memory_region_set_enabled(mr, true);
|
|
|
|
host_memory_backend_set_mapped(ct3d->hostmem, true);
|
2022-04-29 16:40:57 +02:00
|
|
|
|
|
|
|
if (ds->id) {
|
|
|
|
name = g_strdup_printf("cxl-type3-dpa-space:%s", ds->id);
|
|
|
|
} else {
|
|
|
|
name = g_strdup("cxl-type3-dpa-space");
|
|
|
|
}
|
|
|
|
address_space_init(&ct3d->hostmem_as, mr, name);
|
|
|
|
g_free(name);
|
|
|
|
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
ct3d->cxl_dstate.pmem_size = ct3d->hostmem->size;
|
|
|
|
|
2022-04-29 16:40:46 +02:00
|
|
|
if (!ct3d->lsa) {
|
|
|
|
error_setg(errp, "lsa property must be set");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ct3_realize(PCIDevice *pci_dev, Error **errp)
|
|
|
|
{
|
|
|
|
CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
|
|
|
|
CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
|
|
|
|
ComponentRegisters *regs = &cxl_cstate->crb;
|
|
|
|
MemoryRegion *mr = ®s->component_registers;
|
|
|
|
uint8_t *pci_conf = pci_dev->config;
|
|
|
|
|
|
|
|
if (!cxl_setup_memory(ct3d, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pci_config_set_prog_interface(pci_conf, 0x10);
|
|
|
|
pci_config_set_class(pci_conf, PCI_CLASS_MEMORY_CXL);
|
|
|
|
|
|
|
|
pcie_endpoint_cap_init(pci_dev, 0x80);
|
|
|
|
cxl_cstate->dvsec_offset = 0x100;
|
|
|
|
|
|
|
|
ct3d->cxl_cstate.pdev = pci_dev;
|
|
|
|
build_dvsecs(ct3d);
|
|
|
|
|
2022-04-29 16:40:43 +02:00
|
|
|
regs->special_ops = g_new0(MemoryRegionOps, 1);
|
|
|
|
regs->special_ops->write = ct3d_reg_write;
|
|
|
|
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
cxl_component_register_block_init(OBJECT(pci_dev), cxl_cstate,
|
|
|
|
TYPE_CXL_TYPE3);
|
|
|
|
|
|
|
|
pci_register_bar(
|
|
|
|
pci_dev, CXL_COMPONENT_REG_BAR_IDX,
|
|
|
|
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, mr);
|
|
|
|
|
|
|
|
cxl_device_register_block_init(OBJECT(pci_dev), &ct3d->cxl_dstate);
|
|
|
|
pci_register_bar(pci_dev, CXL_DEVICE_REG_BAR_IDX,
|
|
|
|
PCI_BASE_ADDRESS_SPACE_MEMORY |
|
|
|
|
PCI_BASE_ADDRESS_MEM_TYPE_64,
|
|
|
|
&ct3d->cxl_dstate.device_registers);
|
|
|
|
}
|
|
|
|
|
2022-04-29 16:40:43 +02:00
|
|
|
static void ct3_exit(PCIDevice *pci_dev)
|
|
|
|
{
|
|
|
|
CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
|
|
|
|
CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
|
|
|
|
ComponentRegisters *regs = &cxl_cstate->crb;
|
|
|
|
|
|
|
|
g_free(regs->special_ops);
|
2022-04-29 16:40:57 +02:00
|
|
|
address_space_destroy(&ct3d->hostmem_as);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Support multiple HDM decoders and DPA skip */
|
|
|
|
static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa)
|
|
|
|
{
|
|
|
|
uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
|
|
|
|
uint64_t decoder_base, decoder_size, hpa_offset;
|
|
|
|
uint32_t hdm0_ctrl;
|
|
|
|
int ig, iw;
|
|
|
|
|
|
|
|
decoder_base = (((uint64_t)cache_mem[R_CXL_HDM_DECODER0_BASE_HI] << 32) |
|
|
|
|
cache_mem[R_CXL_HDM_DECODER0_BASE_LO]);
|
|
|
|
if ((uint64_t)host_addr < decoder_base) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hpa_offset = (uint64_t)host_addr - decoder_base;
|
|
|
|
|
|
|
|
decoder_size = ((uint64_t)cache_mem[R_CXL_HDM_DECODER0_SIZE_HI] << 32) |
|
|
|
|
cache_mem[R_CXL_HDM_DECODER0_SIZE_LO];
|
|
|
|
if (hpa_offset >= decoder_size) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hdm0_ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL];
|
|
|
|
iw = FIELD_EX32(hdm0_ctrl, CXL_HDM_DECODER0_CTRL, IW);
|
|
|
|
ig = FIELD_EX32(hdm0_ctrl, CXL_HDM_DECODER0_CTRL, IG);
|
|
|
|
|
|
|
|
*dpa = (MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
|
|
|
|
((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset) >> iw);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
|
|
|
|
unsigned size, MemTxAttrs attrs)
|
|
|
|
{
|
|
|
|
CXLType3Dev *ct3d = CXL_TYPE3(d);
|
|
|
|
uint64_t dpa_offset;
|
|
|
|
MemoryRegion *mr;
|
|
|
|
|
|
|
|
/* TODO support volatile region */
|
|
|
|
mr = host_memory_backend_get_memory(ct3d->hostmem);
|
|
|
|
if (!mr) {
|
|
|
|
return MEMTX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cxl_type3_dpa(ct3d, host_addr, &dpa_offset)) {
|
|
|
|
return MEMTX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dpa_offset > int128_get64(mr->size)) {
|
|
|
|
return MEMTX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return address_space_read(&ct3d->hostmem_as, dpa_offset, attrs, data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
|
|
|
|
unsigned size, MemTxAttrs attrs)
|
|
|
|
{
|
|
|
|
CXLType3Dev *ct3d = CXL_TYPE3(d);
|
|
|
|
uint64_t dpa_offset;
|
|
|
|
MemoryRegion *mr;
|
|
|
|
|
|
|
|
mr = host_memory_backend_get_memory(ct3d->hostmem);
|
|
|
|
if (!mr) {
|
|
|
|
return MEMTX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cxl_type3_dpa(ct3d, host_addr, &dpa_offset)) {
|
|
|
|
return MEMTX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dpa_offset > int128_get64(mr->size)) {
|
|
|
|
return MEMTX_OK;
|
|
|
|
}
|
|
|
|
return address_space_write(&ct3d->hostmem_as, dpa_offset, attrs,
|
|
|
|
&data, size);
|
2022-04-29 16:40:43 +02:00
|
|
|
}
|
|
|
|
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
static void ct3d_reset(DeviceState *dev)
|
|
|
|
{
|
|
|
|
CXLType3Dev *ct3d = CXL_TYPE3(dev);
|
|
|
|
uint32_t *reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
|
|
|
|
uint32_t *write_msk = ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;
|
|
|
|
|
|
|
|
cxl_component_register_init_common(reg_state, write_msk, CXL2_TYPE3_DEVICE);
|
|
|
|
cxl_device_register_init_common(&ct3d->cxl_dstate);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Property ct3_props[] = {
|
|
|
|
DEFINE_PROP_LINK("memdev", CXLType3Dev, hostmem, TYPE_MEMORY_BACKEND,
|
|
|
|
HostMemoryBackend *),
|
2022-04-29 16:40:46 +02:00
|
|
|
DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND,
|
|
|
|
HostMemoryBackend *),
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
|
};
|
|
|
|
|
2022-04-29 16:40:45 +02:00
|
|
|
static uint64_t get_lsa_size(CXLType3Dev *ct3d)
|
|
|
|
{
|
2022-04-29 16:40:46 +02:00
|
|
|
MemoryRegion *mr;
|
|
|
|
|
|
|
|
mr = host_memory_backend_get_memory(ct3d->lsa);
|
|
|
|
return memory_region_size(mr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void validate_lsa_access(MemoryRegion *mr, uint64_t size,
|
|
|
|
uint64_t offset)
|
|
|
|
{
|
|
|
|
assert(offset + size <= memory_region_size(mr));
|
|
|
|
assert(offset + size > offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t get_lsa(CXLType3Dev *ct3d, void *buf, uint64_t size,
|
|
|
|
uint64_t offset)
|
|
|
|
{
|
|
|
|
MemoryRegion *mr;
|
|
|
|
void *lsa;
|
|
|
|
|
|
|
|
mr = host_memory_backend_get_memory(ct3d->lsa);
|
|
|
|
validate_lsa_access(mr, size, offset);
|
|
|
|
|
|
|
|
lsa = memory_region_get_ram_ptr(mr) + offset;
|
|
|
|
memcpy(buf, lsa, size);
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
|
|
|
|
uint64_t offset)
|
|
|
|
{
|
|
|
|
MemoryRegion *mr;
|
|
|
|
void *lsa;
|
|
|
|
|
|
|
|
mr = host_memory_backend_get_memory(ct3d->lsa);
|
|
|
|
validate_lsa_access(mr, size, offset);
|
|
|
|
|
|
|
|
lsa = memory_region_get_ram_ptr(mr) + offset;
|
|
|
|
memcpy(lsa, buf, size);
|
|
|
|
memory_region_set_dirty(mr, offset, size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Just like the PMEM, if the guest is not allowed to exit gracefully, label
|
|
|
|
* updates will get lost.
|
|
|
|
*/
|
2022-04-29 16:40:45 +02:00
|
|
|
}
|
|
|
|
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
static void ct3_class_init(ObjectClass *oc, void *data)
|
|
|
|
{
|
|
|
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
|
|
|
PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
|
2022-04-29 16:40:45 +02:00
|
|
|
CXLType3Class *cvc = CXL_TYPE3_CLASS(oc);
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
|
|
|
|
pc->realize = ct3_realize;
|
2022-04-29 16:40:43 +02:00
|
|
|
pc->exit = ct3_exit;
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
|
|
|
|
pc->vendor_id = PCI_VENDOR_ID_INTEL;
|
|
|
|
pc->device_id = 0xd93; /* LVF for now */
|
|
|
|
pc->revision = 1;
|
|
|
|
|
|
|
|
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
|
|
|
dc->desc = "CXL PMEM Device (Type 3)";
|
|
|
|
dc->reset = ct3d_reset;
|
|
|
|
device_class_set_props(dc, ct3_props);
|
2022-04-29 16:40:45 +02:00
|
|
|
|
|
|
|
cvc->get_lsa_size = get_lsa_size;
|
2022-04-29 16:40:46 +02:00
|
|
|
cvc->get_lsa = get_lsa;
|
|
|
|
cvc->set_lsa = set_lsa;
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo ct3d_info = {
|
|
|
|
.name = TYPE_CXL_TYPE3,
|
|
|
|
.parent = TYPE_PCI_DEVICE,
|
2022-04-29 16:40:45 +02:00
|
|
|
.class_size = sizeof(struct CXLType3Class),
|
hw/cxl/device: Add a memory device (8.2.8.5)
A CXL memory device (AKA Type 3) is a CXL component that contains some
combination of volatile and persistent memory. It also implements the
previously defined mailbox interface as well as the memory device
firmware interface.
Although the memory device is configured like a normal PCIe device, the
memory traffic is on an entirely separate bus conceptually (using the
same physical wires as PCIe, but different protocol).
Once the CXL topology is fully configure and address decoders committed,
the guest physical address for the memory device is part of a larger
window which is owned by the platform. The creation of these windows
is later in this series.
The following example will create a 256M device in a 512M window:
-object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
-device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0"
Note: Dropped PCDIMM info interfaces for now. They can be added if
appropriate at a later date.
Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20220429144110.25167-18-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-04-29 16:40:42 +02:00
|
|
|
.class_init = ct3_class_init,
|
|
|
|
.instance_size = sizeof(CXLType3Dev),
|
|
|
|
.interfaces = (InterfaceInfo[]) {
|
|
|
|
{ INTERFACE_CXL_DEVICE },
|
|
|
|
{ INTERFACE_PCIE_DEVICE },
|
|
|
|
{}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ct3d_registers(void)
|
|
|
|
{
|
|
|
|
type_register_static(&ct3d_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(ct3d_registers);
|