@ -65,6 +65,7 @@ enum {
MEDIA_AND_POISON = 0x43 ,
# define GET_POISON_LIST 0x0
# define INJECT_POISON 0x1
# define CLEAR_POISON 0x2
} ;
/* 8.2.8.4.5.1 Command Return Codes */
@ -512,6 +513,85 @@ static CXLRetCode cmd_media_inject_poison(struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS ;
}
static CXLRetCode cmd_media_clear_poison ( struct cxl_cmd * cmd ,
CXLDeviceState * cxl_dstate ,
uint16_t * len_unused )
{
CXLType3Dev * ct3d = container_of ( cxl_dstate , CXLType3Dev , cxl_dstate ) ;
CXLPoisonList * poison_list = & ct3d - > poison_list ;
CXLType3Class * cvc = CXL_TYPE3_GET_CLASS ( ct3d ) ;
struct clear_poison_pl {
uint64_t dpa ;
uint8_t data [ 64 ] ;
} ;
CXLPoison * ent ;
uint64_t dpa ;
struct clear_poison_pl * in = ( void * ) cmd - > payload ;
dpa = ldq_le_p ( & in - > dpa ) ;
if ( dpa + CXL_CACHE_LINE_SIZE > cxl_dstate - > mem_size ) {
return CXL_MBOX_INVALID_PA ;
}
/* Clearing a region with no poison is not an error so always do so */
if ( cvc - > set_cacheline ) {
if ( ! cvc - > set_cacheline ( ct3d , dpa , in - > data ) ) {
return CXL_MBOX_INTERNAL_ERROR ;
}
}
QLIST_FOREACH ( ent , poison_list , node ) {
/*
* Test for contained in entry . Simpler than general case
* as clearing 64 bytes and entries 64 byte aligned
*/
if ( ( dpa > = ent - > start ) & & ( dpa < ent - > start + ent - > length ) ) {
break ;
}
}
if ( ! ent ) {
return CXL_MBOX_SUCCESS ;
}
QLIST_REMOVE ( ent , node ) ;
ct3d - > poison_list_cnt - - ;
if ( dpa > ent - > start ) {
CXLPoison * frag ;
/* Cannot overflow as replacing existing entry */
frag = g_new0 ( CXLPoison , 1 ) ;
frag - > start = ent - > start ;
frag - > length = dpa - ent - > start ;
frag - > type = ent - > type ;
QLIST_INSERT_HEAD ( poison_list , frag , node ) ;
ct3d - > poison_list_cnt + + ;
}
if ( dpa + CXL_CACHE_LINE_SIZE < ent - > start + ent - > length ) {
CXLPoison * frag ;
if ( ct3d - > poison_list_cnt = = CXL_POISON_LIST_LIMIT ) {
cxl_set_poison_list_overflowed ( ct3d ) ;
} else {
frag = g_new0 ( CXLPoison , 1 ) ;
frag - > start = dpa + CXL_CACHE_LINE_SIZE ;
frag - > length = ent - > start + ent - > length - frag - > start ;
frag - > type = ent - > type ;
QLIST_INSERT_HEAD ( poison_list , frag , node ) ;
ct3d - > poison_list_cnt + + ;
}
}
/* Any fragments have been added, free original entry */
g_free ( ent ) ;
return CXL_MBOX_SUCCESS ;
}
# define IMMEDIATE_CONFIG_CHANGE (1 << 1)
# define IMMEDIATE_DATA_CHANGE (1 << 2)
# define IMMEDIATE_POLICY_CHANGE (1 << 3)
@ -543,6 +623,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
cmd_media_get_poison_list , 16 , 0 } ,
[ MEDIA_AND_POISON ] [ INJECT_POISON ] = { " MEDIA_AND_POISON_INJECT_POISON " ,
cmd_media_inject_poison , 8 , 0 } ,
[ MEDIA_AND_POISON ] [ CLEAR_POISON ] = { " MEDIA_AND_POISON_CLEAR_POISON " ,
cmd_media_clear_poison , 72 , 0 } ,
} ;
void cxl_process_mailbox ( CXLDeviceState * cxl_dstate )