Browse Source

hw/cxl: mailbox-utils: 0x5604 - FMAPI Initiate DC Add

FM DCD Management command 0x5604 implemented per CXL r3.2 Spec Section 7.6.7.6.5

Reviewed-by: Fan Ni <fan.ni@samsung.com>
Signed-off-by: Anisa Su <anisa.su@samsung.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20250714174509.1984430-11-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
pull/294/head
Anisa Su 1 year ago
committed by Michael S. Tsirkin
parent
commit
42cbc937d4
  1. 109
      hw/cxl/cxl-mailbox-utils.c
  2. 8
      hw/mem/cxl_type3.c
  3. 4
      include/hw/cxl/cxl_device.h

109
hw/cxl/cxl-mailbox-utils.c

@ -123,6 +123,7 @@ enum {
#define GET_HOST_DC_REGION_CONFIG 0x1
#define SET_DC_REGION_CONFIG 0x2
#define GET_DC_REGION_EXTENT_LIST 0x3
#define INITIATE_DC_ADD 0x4
};
/* CCI Message Format CXL r3.1 Figure 7-19 */
@ -3543,6 +3544,107 @@ static CXLRetCode cmd_fm_get_dc_region_extent_list(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}
/*
* Helper function to convert CXLDCExtentRaw to CXLUpdateDCExtentListInPl
* in order to reuse cxl_detect_malformed_extent_list() function which accepts
* CXLUpdateDCExtentListInPl as a parameter.
*/
static void convert_raw_extents(CXLDCExtentRaw raw_extents[],
CXLUpdateDCExtentListInPl *extent_list,
int count)
{
int i;
extent_list->num_entries_updated = count;
for (i = 0; i < count; i++) {
extent_list->updated_entries[i].start_dpa = raw_extents[i].start_dpa;
extent_list->updated_entries[i].len = raw_extents[i].len;
}
}
/* CXL r3.2 Section 7.6.7.6.5: Initiate Dynamic Capacity Add (Opcode 5604h) */
static CXLRetCode cmd_fm_initiate_dc_add(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
uint8_t *payload_out,
size_t *len_out,
CXLCCI *cci)
{
struct {
uint16_t host_id;
uint8_t selection_policy;
uint8_t reg_num;
uint64_t length;
uint8_t tag[0x10];
uint32_t ext_count;
CXLDCExtentRaw extents[];
} QEMU_PACKED *in = (void *)payload_in;
CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
int i, rc;
switch (in->selection_policy) {
case CXL_EXTENT_SELECTION_POLICY_PRESCRIPTIVE: {
/* Adding extents exceeds device's extent tracking ability. */
if (in->ext_count + ct3d->dc.total_extent_count >
CXL_NUM_EXTENTS_SUPPORTED) {
return CXL_MBOX_RESOURCES_EXHAUSTED;
}
g_autofree CXLUpdateDCExtentListInPl *list =
g_malloc0(sizeof(*list) +
in->ext_count * sizeof(*list->updated_entries));
convert_raw_extents(in->extents, list, in->ext_count);
rc = cxl_detect_malformed_extent_list(ct3d, list);
for (i = 0; i < in->ext_count; i++) {
CXLDCExtentRaw *ext = &in->extents[i];
/* Check requested extents do not overlap with pending ones. */
if (cxl_extent_groups_overlaps_dpa_range(&ct3d->dc.extents_pending,
ext->start_dpa,
ext->len)) {
return CXL_MBOX_INVALID_EXTENT_LIST;
}
/* Check requested extents do not overlap with existing ones. */
if (cxl_extents_overlaps_dpa_range(&ct3d->dc.extents,
ext->start_dpa,
ext->len)) {
return CXL_MBOX_INVALID_EXTENT_LIST;
}
}
if (rc) {
return rc;
}
CXLDCExtentGroup *group = NULL;
for (i = 0; i < in->ext_count; i++) {
CXLDCExtentRaw *ext = &in->extents[i];
group = cxl_insert_extent_to_extent_group(group, ext->start_dpa,
ext->len, ext->tag,
ext->shared_seq);
}
cxl_extent_group_list_insert_tail(&ct3d->dc.extents_pending, group);
ct3d->dc.total_extent_count += in->ext_count;
cxl_create_dc_event_records_for_extents(ct3d,
DC_EVENT_ADD_CAPACITY,
in->extents,
in->ext_count);
return CXL_MBOX_SUCCESS;
}
default: {
qemu_log_mask(LOG_UNIMP,
"CXL extent selection policy not supported.\n");
return CXL_MBOX_INVALID_INPUT;
}
}
}
static const struct cxl_cmd cxl_cmd_set[256][256] = {
[INFOSTAT][BACKGROUND_OPERATION_ABORT] = { "BACKGROUND_OPERATION_ABORT",
cmd_infostat_bg_op_abort, 0, 0 },
@ -3670,6 +3772,13 @@ static const struct cxl_cmd cxl_cmd_set_fm_dcd[256][256] = {
CXL_MBOX_IMMEDIATE_DATA_CHANGE) },
[FMAPI_DCD_MGMT][GET_DC_REGION_EXTENT_LIST] = { "GET_DC_REGION_EXTENT_LIST",
cmd_fm_get_dc_region_extent_list, 12, 0 },
[FMAPI_DCD_MGMT][INITIATE_DC_ADD] = { "INIT_DC_ADD",
cmd_fm_initiate_dc_add, ~0,
(CXL_MBOX_CONFIG_CHANGE_COLD_RESET |
CXL_MBOX_CONFIG_CHANGE_CONV_RESET |
CXL_MBOX_CONFIG_CHANGE_CXL_RESET |
CXL_MBOX_IMMEDIATE_CONFIG_CHANGE |
CXL_MBOX_IMMEDIATE_DATA_CHANGE) },
};
/*

8
hw/mem/cxl_type3.c

@ -1885,8 +1885,8 @@ void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log,
* the list.
* Return value: return true if has overlaps; otherwise, return false
*/
static bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list,
uint64_t dpa, uint64_t len)
bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list,
uint64_t dpa, uint64_t len)
{
CXLDCExtent *ent;
Range range1, range2;
@ -1931,8 +1931,8 @@ bool cxl_extents_contains_dpa_range(CXLDCExtentList *list,
return false;
}
static bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list,
uint64_t dpa, uint64_t len)
bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list,
uint64_t dpa, uint64_t len)
{
CXLDCExtentGroup *group;

4
include/hw/cxl/cxl_device.h

@ -728,4 +728,8 @@ void cxl_create_dc_event_records_for_extents(CXLType3Dev *ct3d,
CXLDCEventType type,
CXLDCExtentRaw extents[],
uint32_t ext_count);
bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list,
uint64_t dpa, uint64_t len);
bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list,
uint64_t dpa, uint64_t len);
#endif

Loading…
Cancel
Save