mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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>
This commit is contained in:
committed by
Michael S. Tsirkin
parent
0a362772e0
commit
42cbc937d4
@@ -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) },
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+4
-4
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user