mirror of https://github.com/xemu-project/xemu.git
mem/cxl_type3: Add read and write functions for associated hostmem.
Once a read or write reaches a CXL type 3 device, the HDM decoders on the device are used to establish the Device Physical Address which should be accessed. These functions peform the required maths and then use a device specific address space to access the hostmem->mr to fullfil the actual operation. Note that failed writes are silent, but failed reads return poison. Note this is based loosely on: https://lore.kernel.org/qemu-devel/20200817161853.593247-6-f4bug@amsat.org/ [RFC PATCH 0/9] hw/misc: Add support for interleaved memory accesses Only lightly tested so far. More complex test cases yet to be written. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Message-Id: <20220429144110.25167-33-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
0b4aec2469
commit
5fcc499ee3
|
@ -97,7 +97,9 @@ static void ct3d_reg_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
|
|
||||||
static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
|
static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
|
||||||
{
|
{
|
||||||
|
DeviceState *ds = DEVICE(ct3d);
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
|
char *name;
|
||||||
|
|
||||||
if (!ct3d->hostmem) {
|
if (!ct3d->hostmem) {
|
||||||
error_setg(errp, "memdev property must be set");
|
error_setg(errp, "memdev property must be set");
|
||||||
|
@ -112,6 +114,15 @@ static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
|
||||||
memory_region_set_nonvolatile(mr, true);
|
memory_region_set_nonvolatile(mr, true);
|
||||||
memory_region_set_enabled(mr, true);
|
memory_region_set_enabled(mr, true);
|
||||||
host_memory_backend_set_mapped(ct3d->hostmem, true);
|
host_memory_backend_set_mapped(ct3d->hostmem, true);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
ct3d->cxl_dstate.pmem_size = ct3d->hostmem->size;
|
ct3d->cxl_dstate.pmem_size = ct3d->hostmem->size;
|
||||||
|
|
||||||
if (!ct3d->lsa) {
|
if (!ct3d->lsa) {
|
||||||
|
@ -167,6 +178,86 @@ static void ct3_exit(PCIDevice *pci_dev)
|
||||||
ComponentRegisters *regs = &cxl_cstate->crb;
|
ComponentRegisters *regs = &cxl_cstate->crb;
|
||||||
|
|
||||||
g_free(regs->special_ops);
|
g_free(regs->special_ops);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ct3d_reset(DeviceState *dev)
|
static void ct3d_reset(DeviceState *dev)
|
||||||
|
|
|
@ -239,6 +239,7 @@ struct CXLType3Dev {
|
||||||
HostMemoryBackend *lsa;
|
HostMemoryBackend *lsa;
|
||||||
|
|
||||||
/* State */
|
/* State */
|
||||||
|
AddressSpace hostmem_as;
|
||||||
CXLComponentState cxl_cstate;
|
CXLComponentState cxl_cstate;
|
||||||
CXLDeviceState cxl_dstate;
|
CXLDeviceState cxl_dstate;
|
||||||
};
|
};
|
||||||
|
@ -259,4 +260,9 @@ struct CXLType3Class {
|
||||||
uint64_t offset);
|
uint64_t offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
|
||||||
|
unsigned size, MemTxAttrs attrs);
|
||||||
|
MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
|
||||||
|
unsigned size, MemTxAttrs attrs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue