Skip to content

Commit

Permalink
hw/cxl: Standardize all references on CXL r3.1 and minor updates
Browse files Browse the repository at this point in the history
Previously not all references mentioned any spec version at all.
Given r3.1 is the current specification available for evaluation at
www.computeexpresslink.org update references to refer to that.
Hopefully this won't become a never ending job.

A few structure definitions have been updated to add new fields.
Defaults of 0 and read only are valid choices for these new DVSEC
registers so go with that for now.

There are additional error codes and some of the 'questions' in
the comments are resolved now.

Update documentation reference to point to the CXL r3.1 specification
with naming closer to what is on the cover.

For cases where there are structure version numbers, add defines
so they can be found next to the register definitions.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20240126121636.24611-6-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
jic23 authored and mstsirkin committed Feb 14, 2024
1 parent 202f651 commit 8700ee1
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 104 deletions.
3 changes: 1 addition & 2 deletions docs/system/devices/cxl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -411,5 +411,4 @@ References

- Consortium website for specifications etc:
http://www.computeexpresslink.org
- Compute Express link Revision 2 specification, October 2020
- CEDT CFMWS & QTG _DSM ECN May 2021
- Compute Express Link (CXL) Specification, Revision 3.1, August 2023
17 changes: 9 additions & 8 deletions hw/cxl/cxl-component-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "hw/pci/pci.h"
#include "hw/cxl/cxl.h"

/* CXL r3.0 Section 8.2.4.19.1 CXL HDM Decoder Capability Register */
/* CXL r3.1 Section 8.2.4.20.1 CXL HDM Decoder Capability Register */
int cxl_decoder_count_enc(int count)
{
switch (count) {
Expand Down Expand Up @@ -160,11 +160,11 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
}

/*
* 8.2.3
* CXL r3.1 Section 8.2.3: Component Register Layout and Definition
* The access restrictions specified in Section 8.2.2 also apply to CXL 2.0
* Component Registers.
*
* 8.2.2
* CXL r3.1 Section 8.2.2: Accessing Component Registers
* • A 32 bit register shall be accessed as a 4 Bytes quantity. Partial
* reads are not permitted.
* • A 64 bit register shall be accessed as a 8 Bytes quantity. Partial
Expand Down Expand Up @@ -308,7 +308,8 @@ void cxl_component_register_init_common(uint32_t *reg_state,

/* CXL Capability Header Register */
ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, ID, 1);
ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, VERSION, 1);
ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, VERSION,
CXL_CAPABILITY_VERSION);
ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, CACHE_MEM_VERSION, 1);
ARRAY_FIELD_DP32(reg_state, CXL_CAPABILITY_HEADER, ARRAY_SIZE, caps);

Expand All @@ -328,7 +329,7 @@ void cxl_component_register_init_common(uint32_t *reg_state,
init_cap_reg(RAS, 2, CXL_RAS_CAPABILITY_VERSION);
ras_init_common(reg_state, write_msk);

init_cap_reg(LINK, 4, 2);
init_cap_reg(LINK, 4, CXL_LINK_CAPABILITY_VERSION);

if (caps < 3) {
return;
Expand All @@ -341,8 +342,8 @@ void cxl_component_register_init_common(uint32_t *reg_state,
return;
}

init_cap_reg(EXTSEC, 6, 1);
init_cap_reg(SNOOP, 8, 1);
init_cap_reg(EXTSEC, 6, CXL_EXTSEC_CAP_VERSION);
init_cap_reg(SNOOP, 8, CXL_SNOOP_CAP_VERSION);

#undef init_cap_reg
}
Expand Down Expand Up @@ -467,7 +468,7 @@ void cxl_component_create_dvsec(CXLComponentState *cxl,
cxl->dvsec_offset += length;
}

/* CXL r3.0 Section 8.2.4.19.7 CXL HDM Decoder n Control Register */
/* CXL r3.1 Section 8.2.4.20.7 CXL HDM Decoder n Control Register */
uint8_t cxl_interleave_ways_enc(int iw, Error **errp)
{
switch (iw) {
Expand Down
8 changes: 5 additions & 3 deletions hw/cxl/cxl-device-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

/*
* Device registers have no restrictions per the spec, and so fall back to the
* default memory mapped register rules in 8.2:
* default memory mapped register rules in CXL r3.1 Section 8.2:
* Software shall use CXL.io Memory Read and Write to access memory mapped
* register defined in this section. Unless otherwise specified, software
* shall restrict the accesses width based on the following:
Expand Down Expand Up @@ -393,13 +393,15 @@ void cxl_device_register_init_t3(CXLType3Dev *ct3d)
ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1);
ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_COUNT, cap_count);

cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1, 2);
cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1,
CXL_DEVICE_STATUS_VERSION);
device_reg_init_common(cxl_dstate);

cxl_device_cap_init(cxl_dstate, MAILBOX, 2, CXL_DEV_MAILBOX_VERSION);
mailbox_reg_init_common(cxl_dstate);

cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000, 1);
cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000,
CXL_MEM_DEV_STATUS_VERSION);
memdev_reg_init_common(cxl_dstate);

cxl_initialize_mailbox_t3(&ct3d->cci, DEVICE(ct3d),
Expand Down
2 changes: 1 addition & 1 deletion hw/cxl/cxl-events.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ CXLRetCode cxl_event_clear_records(CXLDeviceState *cxlds,
* record that will not be cleared when Clear Event Records is executed,
* the device shall return the Invalid Handle return code and shall not
* clear any of the specified event records."
* -- CXL 3.0 8.2.9.2.3
* -- CXL r3.1 Section 8.2.9.2.3: Clear Event Records (0101h)
*/
entry = cxl_event_get_head(log);
for (nr = 0; entry && nr < pl->nr_recs; nr++) {
Expand Down
49 changes: 27 additions & 22 deletions hw/cxl/cxl-mailbox-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ enum {
#define MANAGEMENT_COMMAND 0x0
};

/* CCI Message Format CXL r3.0 Figure 7-19 */
/* CCI Message Format CXL r3.1 Figure 7-19 */
typedef struct CXLCCIMessage {
uint8_t category;
#define CXL_CCI_CAT_REQ 0
Expand Down Expand Up @@ -342,7 +342,7 @@ static CXLRetCode cmd_events_set_interrupt_policy(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.0 section 8.2.9.1.1: Identify (Opcode 0001h) */
/* CXL r3.1 section 8.2.9.1.1: Identify (Opcode 0001h) */
static CXLRetCode cmd_infostat_identify(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -403,7 +403,7 @@ static void cxl_set_dsp_active_bm(PCIBus *b, PCIDevice *d,
}
}

/* CXL r3 8.2.9.1.1 */
/* CXL r3.1 Section 7.6.7.1.1: Identify Switch Device (Opcode 5100h) */
static CXLRetCode cmd_identify_switch_device(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -455,22 +455,22 @@ static CXLRetCode cmd_identify_switch_device(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.0 Section 7.6.7.1.2: Get Physical Port State (Opcode 5101h) */
/* CXL r3.1 Section 7.6.7.1.2: Get Physical Port State (Opcode 5101h) */
static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
uint8_t *payload_out,
size_t *len_out,
CXLCCI *cci)
{
/* CXL r3.0 Table 7-18: Get Physical Port State Request Payload */
/* CXL r3.1 Table 7-17: Get Physical Port State Request Payload */
struct cxl_fmapi_get_phys_port_state_req_pl {
uint8_t num_ports;
uint8_t ports[];
} QEMU_PACKED *in;

/*
* CXL r3.0 Table 7-20: Get Physical Port State Port Information Block
* CXL r3.1 Table 7-19: Get Physical Port State Port Information Block
* Format
*/
struct cxl_fmapi_port_state_info_block {
Expand All @@ -491,7 +491,7 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
uint8_t supported_ld_count;
} QEMU_PACKED;

/* CXL r3.0 Table 7-19: Get Physical Port State Response Payload */
/* CXL r3.1 Table 7-18: Get Physical Port State Response Payload */
struct cxl_fmapi_get_phys_port_state_resp_pl {
uint8_t num_ports;
uint8_t rsv1[3];
Expand Down Expand Up @@ -579,7 +579,7 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.0 8.2.9.1.2 */
/* CXL r3.1 Section 8.2.9.1.2: Background Operation Status (Opcode 0002h) */
static CXLRetCode cmd_infostat_bg_op_sts(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -609,7 +609,7 @@ static CXLRetCode cmd_infostat_bg_op_sts(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* 8.2.9.2.1 */
/* CXL r3.1 Section 8.2.9.3.1: Get FW Info (Opcode 0200h) */
static CXLRetCode cmd_firmware_update_get_info(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len,
Expand Down Expand Up @@ -647,7 +647,7 @@ static CXLRetCode cmd_firmware_update_get_info(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* 8.2.9.3.1 */
/* CXL r3.1 Section 8.2.9.4.1: Get Timestamp (Opcode 0300h) */
static CXLRetCode cmd_timestamp_get(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand All @@ -664,7 +664,7 @@ static CXLRetCode cmd_timestamp_get(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* 8.2.9.3.2 */
/* CXL r3.1 Section 8.2.9.4.2: Set Timestamp (Opcode 0301h) */
static CXLRetCode cmd_timestamp_set(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand All @@ -683,13 +683,13 @@ static CXLRetCode cmd_timestamp_set(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL 3.0 8.2.9.5.2.1 Command Effects Log (CEL) */
/* CXL r3.1 Section 8.2.9.5.2.1: Command Effects Log (CEL) */
static const QemuUUID cel_uuid = {
.data = UUID(0x0da9c0b5, 0xbf41, 0x4b78, 0x8f, 0x79,
0x96, 0xb1, 0x62, 0x3b, 0x3f, 0x17)
};

/* 8.2.9.4.1 */
/* CXL r3.1 Section 8.2.9.5.1: Get Supported Logs (Opcode 0400h) */
static CXLRetCode cmd_logs_get_supported(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand All @@ -715,7 +715,7 @@ static CXLRetCode cmd_logs_get_supported(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* 8.2.9.4.2 */
/* CXL r3.1 Section 8.2.9.5.2: Get Log (Opcode 0401h) */
static CXLRetCode cmd_logs_get_log(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand All @@ -732,14 +732,11 @@ static CXLRetCode cmd_logs_get_log(const struct cxl_cmd *cmd,
get_log = (void *)payload_in;

/*
* 8.2.9.4.2
* The device shall return Invalid Parameter if the Offset or Length
* CXL r3.1 Section 8.2.9.5.2: Get Log (Opcode 0401h)
* The device shall return Invalid Input if the Offset or Length
* fields attempt to access beyond the size of the log as reported by Get
* Supported Logs.
*
* XXX: Spec is wrong, "Invalid Parameter" isn't a thing.
* XXX: Spec doesn't address incorrect UUID incorrectness.
*
* The CEL buffer is large enough to fit all commands in the emulation, so
* the only possible failure would be if the mailbox itself isn't big
* enough.
Expand All @@ -749,7 +746,7 @@ static CXLRetCode cmd_logs_get_log(const struct cxl_cmd *cmd,
}

if (!qemu_uuid_is_equal(&get_log->uuid, &cel_uuid)) {
return CXL_MBOX_UNSUPPORTED;
return CXL_MBOX_INVALID_LOG;
}

/* Store off everything to local variables so we can wipe out the payload */
Expand All @@ -760,7 +757,7 @@ static CXLRetCode cmd_logs_get_log(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* 8.2.9.5.1.1 */
/* CXL r3.1 Section 8.2.9.9.1.1: Identify Memory Device (Opcode 4000h) */
static CXLRetCode cmd_identify_memory_device(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -815,6 +812,7 @@ static CXLRetCode cmd_identify_memory_device(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.1 Section 8.2.9.9.2.1: Get Partition Info (Opcode 4100h) */
static CXLRetCode cmd_ccls_get_partition_info(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -851,6 +849,7 @@ static CXLRetCode cmd_ccls_get_partition_info(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.1 Section 8.2.9.9.2.3: Get LSA (Opcode 4102h) */
static CXLRetCode cmd_ccls_get_lsa(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -879,6 +878,7 @@ static CXLRetCode cmd_ccls_get_lsa(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.1 Section 8.2.9.9.2.4: Set LSA (Opcode 4103h) */
static CXLRetCode cmd_ccls_set_lsa(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -940,7 +940,7 @@ static void __do_sanitization(CXLType3Dev *ct3d)
}

/*
* CXL 3.0 spec section 8.2.9.8.5.1 - Sanitize.
* CXL r3.1 Section 8.2.9.9.5.1: Sanitize (Opcode 4400h)
*
* Once the Sanitize command has started successfully, the device shall be
* placed in the media disabled state. If the command fails or is interrupted
Expand Down Expand Up @@ -1018,7 +1018,10 @@ static CXLRetCode cmd_get_security_state(const struct cxl_cmd *cmd,
*len_out = 4;
return CXL_MBOX_SUCCESS;
}

/*
* CXL r3.1 Section 8.2.9.9.4.1: Get Poison List (Opcode 4300h)
*
* This is very inefficient, but good enough for now!
* Also the payload will always fit, so no need to handle the MORE flag and
* make this stateful. We may want to allow longer poison lists to aid
Expand Down Expand Up @@ -1103,6 +1106,7 @@ static CXLRetCode cmd_media_get_poison_list(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.1 Section 8.2.9.9.4.2: Inject Poison (Opcode 4301h) */
static CXLRetCode cmd_media_inject_poison(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down Expand Up @@ -1146,6 +1150,7 @@ static CXLRetCode cmd_media_inject_poison(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}

/* CXL r3.1 Section 8.2.9.9.4.3: Clear Poison (Opcode 4302h */
static CXLRetCode cmd_media_clear_poison(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
Expand Down
6 changes: 3 additions & 3 deletions hw/mem/cxl_type3.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ static void build_dvsecs(CXLType3Dev *ct3d)
cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
PCIE_CXL_DEVICE_DVSEC_LENGTH,
PCIE_CXL_DEVICE_DVSEC,
PCIE_CXL2_DEVICE_DVSEC_REVID, dvsec);
PCIE_CXL31_DEVICE_DVSEC_REVID, dvsec);

dvsec = (uint8_t *)&(CXLDVSECRegisterLocator){
.rsvd = 0,
Expand All @@ -346,9 +346,9 @@ static void build_dvsecs(CXLType3Dev *ct3d)
.rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
};
cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
PCIE_FLEXBUS_PORT_DVSEC_LENGTH_2_0,
PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH,
PCIE_FLEXBUS_PORT_DVSEC,
PCIE_FLEXBUS_PORT_DVSEC_REVID_2_0, dvsec);
PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec);
}

static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
Expand Down
4 changes: 2 additions & 2 deletions hw/pci-bridge/cxl_downstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ static void build_dvsecs(CXLComponentState *cxl)
.rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
};
cxl_component_create_dvsec(cxl, CXL2_DOWNSTREAM_PORT,
PCIE_FLEXBUS_PORT_DVSEC_LENGTH_2_0,
PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH,
PCIE_FLEXBUS_PORT_DVSEC,
PCIE_FLEXBUS_PORT_DVSEC_REVID_2_0, dvsec);
PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec);

dvsec = (uint8_t *)&(CXLDVSECPortGPF){
.rsvd = 0,
Expand Down
4 changes: 2 additions & 2 deletions hw/pci-bridge/cxl_root_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ static void build_dvsecs(CXLComponentState *cxl)
.rcvd_mod_ts_data_phase1 = 0xef,
};
cxl_component_create_dvsec(cxl, CXL2_ROOT_PORT,
PCIE_FLEXBUS_PORT_DVSEC_LENGTH_2_0,
PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH,
PCIE_FLEXBUS_PORT_DVSEC,
PCIE_FLEXBUS_PORT_DVSEC_REVID_2_0, dvsec);
PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec);

dvsec = (uint8_t *)&(CXLDVSECRegisterLocator){
.rsvd = 0,
Expand Down
4 changes: 2 additions & 2 deletions hw/pci-bridge/cxl_upstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ static void build_dvsecs(CXLComponentState *cxl)
.rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
};
cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT,
PCIE_FLEXBUS_PORT_DVSEC_LENGTH_2_0,
PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH,
PCIE_FLEXBUS_PORT_DVSEC,
PCIE_FLEXBUS_PORT_DVSEC_REVID_2_0, dvsec);
PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec);

dvsec = (uint8_t *)&(CXLDVSECRegisterLocator){
.rsvd = 0,
Expand Down

0 comments on commit 8700ee1

Please sign in to comment.