mirror of https://github.com/xemu-project/xemu.git
hw/cxl/device: Add memory device utilities
Memory devices implement extra capabilities on top of CXL devices. This adds support for that. A large part of memory devices is the mailbox/command interface. All of the mailbox handling is done in the mailbox-utils library. Longer term, new CXL devices that are being emulated may want to handle commands differently, and therefore would need a mechanism to opt in/out of the specific generic handlers. As such, this is considered sufficient for now, but may need more depth in the future. Signed-off-by: Ben Widawsky <ben.widawsky@intel.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20220429144110.25167-8-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
464e14ac43
commit
ce3b4e5c15
|
@ -131,6 +131,31 @@ static void mailbox_reg_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t mdev_reg_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
|
{
|
||||||
|
uint64_t retval = 0;
|
||||||
|
|
||||||
|
retval = FIELD_DP64(retval, CXL_MEM_DEV_STS, MEDIA_STATUS, 1);
|
||||||
|
retval = FIELD_DP64(retval, CXL_MEM_DEV_STS, MBOX_READY, 1);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MemoryRegionOps mdev_ops = {
|
||||||
|
.read = mdev_reg_read,
|
||||||
|
.write = NULL, /* memory device register is read only */
|
||||||
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
|
.valid = {
|
||||||
|
.min_access_size = 1,
|
||||||
|
.max_access_size = 8,
|
||||||
|
.unaligned = false,
|
||||||
|
},
|
||||||
|
.impl = {
|
||||||
|
.min_access_size = 8,
|
||||||
|
.max_access_size = 8,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const MemoryRegionOps mailbox_ops = {
|
static const MemoryRegionOps mailbox_ops = {
|
||||||
.read = mailbox_reg_read,
|
.read = mailbox_reg_read,
|
||||||
.write = mailbox_reg_write,
|
.write = mailbox_reg_write,
|
||||||
|
@ -188,6 +213,9 @@ void cxl_device_register_block_init(Object *obj, CXLDeviceState *cxl_dstate)
|
||||||
"device-status", CXL_DEVICE_STATUS_REGISTERS_LENGTH);
|
"device-status", CXL_DEVICE_STATUS_REGISTERS_LENGTH);
|
||||||
memory_region_init_io(&cxl_dstate->mailbox, obj, &mailbox_ops, cxl_dstate,
|
memory_region_init_io(&cxl_dstate->mailbox, obj, &mailbox_ops, cxl_dstate,
|
||||||
"mailbox", CXL_MAILBOX_REGISTERS_LENGTH);
|
"mailbox", CXL_MAILBOX_REGISTERS_LENGTH);
|
||||||
|
memory_region_init_io(&cxl_dstate->memory_device, obj, &mdev_ops,
|
||||||
|
cxl_dstate, "memory device caps",
|
||||||
|
CXL_MEMORY_DEVICE_REGISTERS_LENGTH);
|
||||||
|
|
||||||
memory_region_add_subregion(&cxl_dstate->device_registers, 0,
|
memory_region_add_subregion(&cxl_dstate->device_registers, 0,
|
||||||
&cxl_dstate->caps);
|
&cxl_dstate->caps);
|
||||||
|
@ -197,6 +225,9 @@ void cxl_device_register_block_init(Object *obj, CXLDeviceState *cxl_dstate)
|
||||||
memory_region_add_subregion(&cxl_dstate->device_registers,
|
memory_region_add_subregion(&cxl_dstate->device_registers,
|
||||||
CXL_MAILBOX_REGISTERS_OFFSET,
|
CXL_MAILBOX_REGISTERS_OFFSET,
|
||||||
&cxl_dstate->mailbox);
|
&cxl_dstate->mailbox);
|
||||||
|
memory_region_add_subregion(&cxl_dstate->device_registers,
|
||||||
|
CXL_MEMORY_DEVICE_REGISTERS_OFFSET,
|
||||||
|
&cxl_dstate->memory_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_reg_init_common(CXLDeviceState *cxl_dstate) { }
|
static void device_reg_init_common(CXLDeviceState *cxl_dstate) { }
|
||||||
|
@ -209,10 +240,12 @@ static void mailbox_reg_init_common(CXLDeviceState *cxl_dstate)
|
||||||
cxl_dstate->payload_size = CXL_MAILBOX_MAX_PAYLOAD_SIZE;
|
cxl_dstate->payload_size = CXL_MAILBOX_MAX_PAYLOAD_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void memdev_reg_init_common(CXLDeviceState *cxl_dstate) { }
|
||||||
|
|
||||||
void cxl_device_register_init_common(CXLDeviceState *cxl_dstate)
|
void cxl_device_register_init_common(CXLDeviceState *cxl_dstate)
|
||||||
{
|
{
|
||||||
uint64_t *cap_hdrs = cxl_dstate->caps_reg_state64;
|
uint64_t *cap_hdrs = cxl_dstate->caps_reg_state64;
|
||||||
const int cap_count = 2;
|
const int cap_count = 3;
|
||||||
|
|
||||||
/* CXL Device Capabilities Array Register */
|
/* CXL Device Capabilities Array Register */
|
||||||
ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_ID, 0);
|
ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_ID, 0);
|
||||||
|
@ -225,5 +258,8 @@ void cxl_device_register_init_common(CXLDeviceState *cxl_dstate)
|
||||||
cxl_device_cap_init(cxl_dstate, MAILBOX, 2);
|
cxl_device_cap_init(cxl_dstate, MAILBOX, 2);
|
||||||
mailbox_reg_init_common(cxl_dstate);
|
mailbox_reg_init_common(cxl_dstate);
|
||||||
|
|
||||||
|
cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000);
|
||||||
|
memdev_reg_init_common(cxl_dstate);
|
||||||
|
|
||||||
assert(cxl_initialize_mailbox(cxl_dstate) == 0);
|
assert(cxl_initialize_mailbox(cxl_dstate) == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,15 +72,20 @@
|
||||||
#define CXL_MAILBOX_REGISTERS_LENGTH \
|
#define CXL_MAILBOX_REGISTERS_LENGTH \
|
||||||
(CXL_MAILBOX_REGISTERS_SIZE + CXL_MAILBOX_MAX_PAYLOAD_SIZE)
|
(CXL_MAILBOX_REGISTERS_SIZE + CXL_MAILBOX_MAX_PAYLOAD_SIZE)
|
||||||
|
|
||||||
#define CXL_MMIO_SIZE \
|
#define CXL_MEMORY_DEVICE_REGISTERS_OFFSET \
|
||||||
(CXL_DEVICE_CAP_REG_SIZE + CXL_DEVICE_STATUS_REGISTERS_LENGTH + \
|
(CXL_MAILBOX_REGISTERS_OFFSET + CXL_MAILBOX_REGISTERS_LENGTH)
|
||||||
CXL_MAILBOX_REGISTERS_LENGTH)
|
#define CXL_MEMORY_DEVICE_REGISTERS_LENGTH 0x8
|
||||||
|
|
||||||
|
#define CXL_MMIO_SIZE \
|
||||||
|
(CXL_DEVICE_CAP_REG_SIZE + CXL_DEVICE_STATUS_REGISTERS_LENGTH + \
|
||||||
|
CXL_MAILBOX_REGISTERS_LENGTH + CXL_MEMORY_DEVICE_REGISTERS_LENGTH)
|
||||||
|
|
||||||
typedef struct cxl_device_state {
|
typedef struct cxl_device_state {
|
||||||
MemoryRegion device_registers;
|
MemoryRegion device_registers;
|
||||||
|
|
||||||
/* mmio for device capabilities array - 8.2.8.2 */
|
/* mmio for device capabilities array - 8.2.8.2 */
|
||||||
MemoryRegion device;
|
MemoryRegion device;
|
||||||
|
MemoryRegion memory_device;
|
||||||
struct {
|
struct {
|
||||||
MemoryRegion caps;
|
MemoryRegion caps;
|
||||||
union {
|
union {
|
||||||
|
@ -153,6 +158,9 @@ REG64(CXL_DEV_CAP_ARRAY, 0) /* Documented as 128 bit register but 64 byte access
|
||||||
CXL_DEVICE_CAPABILITY_HEADER_REGISTER(DEVICE_STATUS, CXL_DEVICE_CAP_HDR1_OFFSET)
|
CXL_DEVICE_CAPABILITY_HEADER_REGISTER(DEVICE_STATUS, CXL_DEVICE_CAP_HDR1_OFFSET)
|
||||||
CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MAILBOX, CXL_DEVICE_CAP_HDR1_OFFSET + \
|
CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MAILBOX, CXL_DEVICE_CAP_HDR1_OFFSET + \
|
||||||
CXL_DEVICE_CAP_REG_SIZE)
|
CXL_DEVICE_CAP_REG_SIZE)
|
||||||
|
CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MEMORY_DEVICE,
|
||||||
|
CXL_DEVICE_CAP_HDR1_OFFSET +
|
||||||
|
CXL_DEVICE_CAP_REG_SIZE * 2)
|
||||||
|
|
||||||
int cxl_initialize_mailbox(CXLDeviceState *cxl_dstate);
|
int cxl_initialize_mailbox(CXLDeviceState *cxl_dstate);
|
||||||
void cxl_process_mailbox(CXLDeviceState *cxl_dstate);
|
void cxl_process_mailbox(CXLDeviceState *cxl_dstate);
|
||||||
|
@ -209,4 +217,11 @@ REG64(CXL_DEV_BG_CMD_STS, 0x18)
|
||||||
/* CXL 2.0 8.2.8.4.8 Command Payload Registers */
|
/* CXL 2.0 8.2.8.4.8 Command Payload Registers */
|
||||||
REG32(CXL_DEV_CMD_PAYLOAD, 0x20)
|
REG32(CXL_DEV_CMD_PAYLOAD, 0x20)
|
||||||
|
|
||||||
|
REG64(CXL_MEM_DEV_STS, 0)
|
||||||
|
FIELD(CXL_MEM_DEV_STS, FATAL, 0, 1)
|
||||||
|
FIELD(CXL_MEM_DEV_STS, FW_HALT, 1, 1)
|
||||||
|
FIELD(CXL_MEM_DEV_STS, MEDIA_STATUS, 2, 2)
|
||||||
|
FIELD(CXL_MEM_DEV_STS, MBOX_READY, 4, 1)
|
||||||
|
FIELD(CXL_MEM_DEV_STS, RESET_NEEDED, 5, 3)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue