@ -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 ) } ,
} ;
/*