Signed-off-by: Ben Widawsky <ben.widaw...@intel.com> --- hw/cxl/cxl-mailbox-utils.c | 50 +++++++++++++++++++++++++++++++++ hw/mem/cxl_type3.c | 56 ++++++++++++++++++++++++++++++++++++- include/hw/cxl/cxl_device.h | 9 ++++++ 3 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index 2637250c7b..c133cf0341 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -55,6 +55,8 @@ enum { #define MEMORY_DEVICE 0x0 CCLS = 0x41, #define GET_PARTITION_INFO 0x0 + #define GET_LSA 0x2 + #define SET_LSA 0x3 }; /* 8.2.8.4.5.1 Command Return Codes */ @@ -136,8 +138,11 @@ declare_mailbox_handler(LOGS_GET_SUPPORTED); declare_mailbox_handler(LOGS_GET_LOG); declare_mailbox_handler(IDENTIFY_MEMORY_DEVICE); declare_mailbox_handler(CCLS_GET_PARTITION_INFO); +declare_mailbox_handler(CCLS_GET_LSA); +declare_mailbox_handler(CCLS_SET_LSA); #define IMMEDIATE_CONFIG_CHANGE (1 << 1) +#define IMMEDIATE_DATA_CHANGE (1 << 1) #define IMMEDIATE_POLICY_CHANGE (1 << 3) #define IMMEDIATE_LOG_CHANGE (1 << 4) @@ -156,6 +161,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = { CXL_CMD(LOGS, GET_LOG, 0x18, 0), CXL_CMD(IDENTIFY, MEMORY_DEVICE, 0, 0), CXL_CMD(CCLS, GET_PARTITION_INFO, 0, 0), + CXL_CMD(CCLS, GET_LSA, 0, 0), + CXL_CMD(CCLS, SET_LSA, ~0, IMMEDIATE_CONFIG_CHANGE | IMMEDIATE_DATA_CHANGE), }; #undef CXL_CMD @@ -365,6 +372,49 @@ define_mailbox_handler(CCLS_GET_PARTITION_INFO) return CXL_MBOX_SUCCESS; } +define_mailbox_handler(CCLS_GET_LSA) +{ + struct { + uint32_t offset; + uint32_t length; + } __attribute__((packed, __aligned__(16))) *get_lsa; + CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate); + CXLType3Class *cvc = CXL_TYPE3_DEV_GET_CLASS(ct3d); + uint32_t offset, length; + + get_lsa = (void *)cmd->payload; + offset = get_lsa->offset; + length = get_lsa->length; + + *len = 0; + if (offset + length > cvc->get_lsa_size(ct3d)) { + return CXL_MBOX_INVALID_INPUT; + } + + *len = cvc->get_lsa(ct3d, get_lsa, length, offset); + return CXL_MBOX_SUCCESS; +} + +define_mailbox_handler(CCLS_SET_LSA) +{ + struct { + uint32_t offset; + uint32_t rsvd; + void *data; + } __attribute__((packed, __aligned__(16))) *set_lsa = (void *)cmd->payload; + CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate); + CXLType3Class *cvc = CXL_TYPE3_DEV_GET_CLASS(ct3d); + uint16_t plen = *len; + + *len = 0; + if ((set_lsa->offset + plen) > cvc->get_lsa_size(ct3d)) { + return CXL_MBOX_INVALID_INPUT; + } + + cvc->set_lsa(ct3d, set_lsa->data, plen, set_lsa->offset); + return CXL_MBOX_SUCCESS; +} + void cxl_process_mailbox(CXLDeviceState *cxl_dstate) { uint16_t ret = CXL_MBOX_SUCCESS; diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 074d1dd41f..d091e645aa 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -8,6 +8,7 @@ #include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/pmem.h" #include "qemu/range.h" #include "qemu/rcu.h" #include "sysemu/hostmem.h" @@ -148,6 +149,11 @@ static void cxl_setup_memory(CXLType3Dev *ct3d, Error **errp) return; } + if (!ct3d->lsa) { + error_setg(errp, "lsa property must be set"); + return; + } + /* FIXME: need to check mr is the host bridge's MR */ mr = host_memory_backend_get_memory(ct3d->hostmem); @@ -267,6 +273,8 @@ static Property ct3_props[] = { DEFINE_PROP_SIZE("size", CXLType3Dev, size, -1), DEFINE_PROP_LINK("memdev", CXLType3Dev, hostmem, TYPE_MEMORY_BACKEND, HostMemoryBackend *), + DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND, + HostMemoryBackend *), DEFINE_PROP_END_OF_LIST(), }; @@ -297,7 +305,51 @@ static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md, static uint64_t get_lsa_size(CXLType3Dev *ct3d) { - return 0; + 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. + */ } static void ct3_class_init(ObjectClass *oc, void *data) @@ -325,6 +377,8 @@ static void ct3_class_init(ObjectClass *oc, void *data) mdc->set_addr = cxl_md_set_addr; cvc->get_lsa_size = get_lsa_size; + cvc->get_lsa = get_lsa; + cvc->set_lsa = set_lsa; } static const TypeInfo ct3d_info = { diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index a79a0f106c..1869876ef6 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -233,7 +233,11 @@ typedef struct cxl_type3_dev { CXLDeviceState cxl_dstate; } CXLType3Dev; +#ifndef TYPE_CXL_TYPE3_DEV +#define TYPE_CXL_TYPE3_DEV "cxl-type3" +#endif #define CT3(obj) OBJECT_CHECK(CXLType3Dev, (obj), TYPE_CXL_TYPE3_DEV) +OBJECT_DECLARE_TYPE(CXLType3Device, CXLType3Class, CXL_TYPE3_DEV) struct CXLType3Class { /* Private */ @@ -241,6 +245,11 @@ struct CXLType3Class { /* public */ uint64_t (*get_lsa_size)(CXLType3Dev *ct3d); + + uint64_t (*get_lsa)(CXLType3Dev *ct3d, void *buf, uint64_t size, + uint64_t offset); + void (*set_lsa)(CXLType3Dev *ct3d, const void *buf, uint64_t size, + uint64_t offset); }; #endif -- 2.30.0