|
|
|
@ -89,6 +89,7 @@ enum { |
|
|
|
SANITIZE = 0x44, |
|
|
|
#define OVERWRITE 0x0 |
|
|
|
#define SECURE_ERASE 0x1 |
|
|
|
#define MEDIA_OPERATIONS 0x2 |
|
|
|
PERSISTENT_MEM = 0x45, |
|
|
|
#define GET_SECURITY_STATE 0x0 |
|
|
|
MEDIA_AND_POISON = 0x43, |
|
|
|
@ -1705,6 +1706,126 @@ static CXLRetCode cmd_sanitize_overwrite(const struct cxl_cmd *cmd, |
|
|
|
return CXL_MBOX_BG_STARTED; |
|
|
|
} |
|
|
|
|
|
|
|
enum { |
|
|
|
MEDIA_OP_CLASS_GENERAL = 0x0, |
|
|
|
#define MEDIA_OP_GEN_SUBC_DISCOVERY 0x0 |
|
|
|
MEDIA_OP_CLASS_SANITIZE = 0x1, |
|
|
|
#define MEDIA_OP_SAN_SUBC_SANITIZE 0x0 |
|
|
|
#define MEDIA_OP_SAN_SUBC_ZERO 0x1 |
|
|
|
}; |
|
|
|
|
|
|
|
struct media_op_supported_list_entry { |
|
|
|
uint8_t media_op_class; |
|
|
|
uint8_t media_op_subclass; |
|
|
|
}; |
|
|
|
|
|
|
|
struct media_op_discovery_out_pl { |
|
|
|
uint64_t dpa_range_granularity; |
|
|
|
uint16_t total_supported_operations; |
|
|
|
uint16_t num_of_supported_operations; |
|
|
|
struct media_op_supported_list_entry entry[]; |
|
|
|
} QEMU_PACKED; |
|
|
|
|
|
|
|
static const struct media_op_supported_list_entry media_op_matrix[] = { |
|
|
|
{ MEDIA_OP_CLASS_GENERAL, MEDIA_OP_GEN_SUBC_DISCOVERY }, |
|
|
|
{ MEDIA_OP_CLASS_SANITIZE, MEDIA_OP_SAN_SUBC_SANITIZE }, |
|
|
|
{ MEDIA_OP_CLASS_SANITIZE, MEDIA_OP_SAN_SUBC_ZERO }, |
|
|
|
}; |
|
|
|
|
|
|
|
static CXLRetCode media_operations_discovery(uint8_t *payload_in, |
|
|
|
size_t len_in, |
|
|
|
uint8_t *payload_out, |
|
|
|
size_t *len_out) |
|
|
|
{ |
|
|
|
struct { |
|
|
|
uint8_t media_operation_class; |
|
|
|
uint8_t media_operation_subclass; |
|
|
|
uint8_t rsvd[2]; |
|
|
|
uint32_t dpa_range_count; |
|
|
|
struct { |
|
|
|
uint16_t start_index; |
|
|
|
uint16_t num_ops; |
|
|
|
} discovery_osa; |
|
|
|
} QEMU_PACKED *media_op_in_disc_pl = (void *)payload_in; |
|
|
|
struct media_op_discovery_out_pl *media_out_pl = |
|
|
|
(struct media_op_discovery_out_pl *)payload_out; |
|
|
|
int num_ops, start_index, i; |
|
|
|
int count = 0; |
|
|
|
|
|
|
|
if (len_in < sizeof(*media_op_in_disc_pl)) { |
|
|
|
return CXL_MBOX_INVALID_PAYLOAD_LENGTH; |
|
|
|
} |
|
|
|
|
|
|
|
num_ops = media_op_in_disc_pl->discovery_osa.num_ops; |
|
|
|
start_index = media_op_in_disc_pl->discovery_osa.start_index; |
|
|
|
|
|
|
|
/*
|
|
|
|
* As per spec CXL r3.2 8.2.10.9.5.3 dpa_range_count should be zero and |
|
|
|
* start index should not exceed the total number of entries for discovery |
|
|
|
* sub class command. |
|
|
|
*/ |
|
|
|
if (media_op_in_disc_pl->dpa_range_count || |
|
|
|
start_index > ARRAY_SIZE(media_op_matrix)) { |
|
|
|
return CXL_MBOX_INVALID_INPUT; |
|
|
|
} |
|
|
|
|
|
|
|
media_out_pl->dpa_range_granularity = CXL_CACHE_LINE_SIZE; |
|
|
|
media_out_pl->total_supported_operations = |
|
|
|
ARRAY_SIZE(media_op_matrix); |
|
|
|
if (num_ops > 0) { |
|
|
|
for (i = start_index; i < start_index + num_ops; i++) { |
|
|
|
media_out_pl->entry[count].media_op_class = |
|
|
|
media_op_matrix[i].media_op_class; |
|
|
|
media_out_pl->entry[count].media_op_subclass = |
|
|
|
media_op_matrix[i].media_op_subclass; |
|
|
|
count++; |
|
|
|
if (count == num_ops) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
media_out_pl->num_of_supported_operations = count; |
|
|
|
*len_out = sizeof(*media_out_pl) + count * sizeof(*media_out_pl->entry); |
|
|
|
return CXL_MBOX_SUCCESS; |
|
|
|
} |
|
|
|
|
|
|
|
static CXLRetCode cmd_media_operations(const struct cxl_cmd *cmd, |
|
|
|
uint8_t *payload_in, |
|
|
|
size_t len_in, |
|
|
|
uint8_t *payload_out, |
|
|
|
size_t *len_out, |
|
|
|
CXLCCI *cci) |
|
|
|
{ |
|
|
|
struct { |
|
|
|
uint8_t media_operation_class; |
|
|
|
uint8_t media_operation_subclass; |
|
|
|
uint8_t rsvd[2]; |
|
|
|
uint32_t dpa_range_count; |
|
|
|
} QEMU_PACKED *media_op_in_common_pl = (void *)payload_in; |
|
|
|
uint8_t media_op_cl = 0; |
|
|
|
uint8_t media_op_subclass = 0; |
|
|
|
|
|
|
|
if (len_in < sizeof(*media_op_in_common_pl)) { |
|
|
|
return CXL_MBOX_INVALID_PAYLOAD_LENGTH; |
|
|
|
} |
|
|
|
|
|
|
|
media_op_cl = media_op_in_common_pl->media_operation_class; |
|
|
|
media_op_subclass = media_op_in_common_pl->media_operation_subclass; |
|
|
|
|
|
|
|
switch (media_op_cl) { |
|
|
|
case MEDIA_OP_CLASS_GENERAL: |
|
|
|
if (media_op_subclass != MEDIA_OP_GEN_SUBC_DISCOVERY) { |
|
|
|
return CXL_MBOX_UNSUPPORTED; |
|
|
|
} |
|
|
|
|
|
|
|
return media_operations_discovery(payload_in, len_in, payload_out, |
|
|
|
len_out); |
|
|
|
default: |
|
|
|
return CXL_MBOX_UNSUPPORTED; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static CXLRetCode cmd_get_security_state(const struct cxl_cmd *cmd, |
|
|
|
uint8_t *payload_in, |
|
|
|
size_t len_in, |
|
|
|
@ -2850,6 +2971,10 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = { |
|
|
|
CXL_MBOX_SECURITY_STATE_CHANGE | |
|
|
|
CXL_MBOX_BACKGROUND_OPERATION | |
|
|
|
CXL_MBOX_BACKGROUND_OPERATION_ABORT)}, |
|
|
|
[SANITIZE][MEDIA_OPERATIONS] = { "MEDIA_OPERATIONS", cmd_media_operations, |
|
|
|
~0, |
|
|
|
(CXL_MBOX_IMMEDIATE_DATA_CHANGE | |
|
|
|
CXL_MBOX_BACKGROUND_OPERATION)}, |
|
|
|
[PERSISTENT_MEM][GET_SECURITY_STATE] = { "GET_SECURITY_STATE", |
|
|
|
cmd_get_security_state, 0, 0 }, |
|
|
|
[MEDIA_AND_POISON][GET_POISON_LIST] = { "MEDIA_AND_POISON_GET_POISON_LIST", |
|
|
|
|