[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] hw/cxl/cxl-mailbox-utils: Add support for Media operations S
From: |
Vinayak Holikatti |
Subject: |
[PATCH 2/2] hw/cxl/cxl-mailbox-utils: Add support for Media operations Sanitize and Write Zeros commands (8.2.9.9.5.3) |
Date: |
Thu, 23 Jan 2025 10:39:03 +0530 |
CXL spec 3.1 section 8.2.9.9.5.3 describes media operations commands.
CXL devices supports media operations Sanitize and Write zero command.
Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
---
hw/cxl/cxl-mailbox-utils.c | 217 ++++++++++++++++++++++++++++++++++--
include/hw/cxl/cxl_device.h | 11 ++
2 files changed, 220 insertions(+), 8 deletions(-)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 2315d07fb1..89847ddd9d 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -1722,6 +1722,145 @@ static CXLRetCode cmd_sanitize_overwrite(const struct
cxl_cmd *cmd,
return CXL_MBOX_BG_STARTED;
}
+#define DPA_RANGE_GRANULARITY 64
+struct dpa_range_list_entry {
+ uint64_t starting_dpa;
+ uint64_t length;
+};
+
+static int validate_dpa_addr(CXLType3Dev *ct3d, uint64_t dpa_addr,
+ size_t length)
+{
+ MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL;
+ uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0;
+ int rc = 0;
+
+ if ((dpa_addr % DPA_RANGE_GRANULARITY) ||
+ (length % DPA_RANGE_GRANULARITY)) {
+ return -EINVAL;
+ }
+
+ if (ct3d->hostvmem) {
+ vmr = host_memory_backend_get_memory(ct3d->hostvmem);
+ vmr_size = memory_region_size(vmr);
+ }
+ if (ct3d->hostpmem) {
+ pmr = host_memory_backend_get_memory(ct3d->hostpmem);
+ pmr_size = memory_region_size(pmr);
+ }
+ if (ct3d->dc.host_dc) {
+ dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
+ dc_size = memory_region_size(dc_mr);
+ }
+
+ if (!vmr && !pmr && !dc_mr) {
+ return -ENODEV;
+ }
+
+ if (dpa_addr >= vmr_size + pmr_size + dc_size ||
+ (dpa_addr + length) > vmr_size + pmr_size + dc_size) {
+ return -EINVAL;
+ }
+
+ if (dpa_addr > vmr_size + pmr_size) {
+ if (!ct3_test_region_block_backed(ct3d, dpa_addr, length)) {
+ return -ENODEV;
+ }
+ }
+
+
+ return rc;
+}
+
+static int sanitize_range(CXLType3Dev *ct3d, uint64_t dpa_addr, size_t length,
+ uint8_t fill_value)
+{
+
+ MemoryRegion *vmr = NULL, *pmr = NULL;
+ uint64_t vmr_size = 0, pmr_size = 0;
+ AddressSpace *as = NULL;
+ MemTxAttrs mem_attrs = {0};
+
+ if (ct3d->hostvmem) {
+ vmr = host_memory_backend_get_memory(ct3d->hostvmem);
+ vmr_size = memory_region_size(vmr);
+ }
+ if (ct3d->hostpmem) {
+ pmr = host_memory_backend_get_memory(ct3d->hostpmem);
+ pmr_size = memory_region_size(pmr);
+ }
+
+ if (dpa_addr < vmr_size) {
+ as = &ct3d->hostvmem_as;
+ } else if (dpa_addr < vmr_size + pmr_size) {
+ as = &ct3d->hostpmem_as;
+ } else {
+ if (!ct3_test_region_block_backed(ct3d, dpa_addr, length)) {
+ return -ENODEV;
+ }
+ as = &ct3d->dc.host_dc_as;
+ }
+
+ return address_space_set(as, dpa_addr,
+ fill_value, length, mem_attrs);
+}
+
+/* Perform the actual device zeroing */
+static void __do_sanitize(CXLType3Dev *ct3d)
+{
+ struct CXLSanitizeInfo *san_info = ct3d->media_op_sanitize;
+ int dpa_range_count = san_info->dpa_range_count;
+ int rc = 0;
+
+ for (int i = 0; i < dpa_range_count; i++) {
+ rc = sanitize_range(ct3d, san_info->dpa_range_list[i].starting_dpa,
+ san_info->dpa_range_list[i].length, san_info->fill_value);
+ if (rc) {
+ goto exit;
+ }
+ }
+ cxl_discard_all_event_records(&ct3d->cxl_dstate);
+exit:
+ g_free(ct3d->media_op_sanitize);
+ ct3d->media_op_sanitize = NULL;
+ return;
+}
+
+static int get_sanitize_duration(uint64_t total_mem)
+{
+ int secs = 0;
+
+ if (total_mem <= 512) {
+ secs = 4;
+ } else if (total_mem <= 1024) {
+ secs = 8;
+ } else if (total_mem <= 2 * 1024) {
+ secs = 15;
+ } else if (total_mem <= 4 * 1024) {
+ secs = 30;
+ } else if (total_mem <= 8 * 1024) {
+ secs = 60;
+ } else if (total_mem <= 16 * 1024) {
+ secs = 2 * 60;
+ } else if (total_mem <= 32 * 1024) {
+ secs = 4 * 60;
+ } else if (total_mem <= 64 * 1024) {
+ secs = 8 * 60;
+ } else if (total_mem <= 128 * 1024) {
+ secs = 15 * 60;
+ } else if (total_mem <= 256 * 1024) {
+ secs = 30 * 60;
+ } else if (total_mem <= 512 * 1024) {
+ secs = 60 * 60;
+ } else if (total_mem <= 1024 * 1024) {
+ secs = 120 * 60;
+ } else {
+ secs = 240 * 60; /* max 4 hrs */
+ }
+
+ return secs;
+}
+
enum {
MEDIA_OP_GENERAL = 0x0,
MEDIA_OP_SANITIZE = 0x1,
@@ -1729,10 +1868,9 @@ enum {
} MEDIA_OPERATION_CLASS;
enum {
- MEDIA_OP_SUB_DISCOVERY = 0x0,
- MEDIA_OP_SUB_SANITIZE = 0x0,
- MEDIA_OP_SUB_ZERO = 0x1,
- MEDIA_OP_SUB_CLASS_MAX
+ MEDIA_OP_GEN_DISCOVERY = 0x0,
+ MEDIA_OP_SAN_SANITIZE = 0x0,
+ MEDIA_OP_SAN_ZERO = 0x1,
} MEDIA_OPERATION_SUB_CLASS;
struct media_op_supported_list_entry {
@@ -1777,9 +1915,14 @@ static CXLRetCode cmd_media_operations(const struct
cxl_cmd *cmd,
};
} QEMU_PACKED *media_op_in_pl = (void *)payload_in;
+
+ CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
uint8_t media_op_cl = media_op_in_pl->media_operation_class;
uint8_t media_op_subclass = media_op_in_pl->media_operation_subclass;
uint32_t dpa_range_count = media_op_in_pl->dpa_range_count;
+ uint8_t fill_value = 0;
+ uint64_t total_mem = 0;
+ int secs = 0;
if (len_in < sizeof(*media_op_in_pl)) {
return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
@@ -1788,7 +1931,7 @@ static CXLRetCode cmd_media_operations(const struct
cxl_cmd *cmd,
switch (media_op_cl) {
case MEDIA_OP_GENERAL:
switch (media_op_subclass) {
- case MEDIA_OP_SUB_DISCOVERY:
+ case MEDIA_OP_GEN_DISCOVERY:
int count = 0;
struct media_op_discovery_out_pl *media_out_pl =
(void *)payload_out;
@@ -1806,7 +1949,7 @@ static CXLRetCode cmd_media_operations(const struct
cxl_cmd *cmd,
return CXL_MBOX_INVALID_INPUT;
}
- media_out_pl->dpa_range_granularity = CXL_CAPACITY_MULTIPLIER;
+ media_out_pl->dpa_range_granularity = DPA_RANGE_GRANULARITY;
media_out_pl->total_supported_operations = MAX_SUPPORTED_OPS;
if (num_ops > 0) {
for (int i = start_index; i < MAX_SUPPORTED_OPS; i++) {
@@ -1824,22 +1967,73 @@ disc_out:
media_out_pl->num_of_supported_operations = count;
*len_out = sizeof(struct media_op_discovery_out_pl) +
(sizeof(struct media_op_supported_list_entry) * count);
- break;
+ goto exit;
default:
return CXL_MBOX_UNSUPPORTED;
}
break;
case MEDIA_OP_SANITIZE:
+ {
switch (media_op_subclass) {
-
+ case MEDIA_OP_SAN_SANITIZE:
+ if (len_in < (sizeof(*media_op_in_pl) +
+ (dpa_range_count * sizeof(struct dpa_range_list_entry)))) {
+ return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
+ }
+ fill_value = 0xF;
+ goto sanitize_range;
+ case MEDIA_OP_SAN_ZERO:
+ if (len_in < (sizeof(*media_op_in_pl) +
+ (dpa_range_count * sizeof(struct dpa_range_list_entry)))) {
+ return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
+ }
+ fill_value = 0;
+ goto sanitize_range;
default:
return CXL_MBOX_UNSUPPORTED;
}
break;
+ }
default:
return CXL_MBOX_UNSUPPORTED;
}
+sanitize_range:
+ if (dpa_range_count > 0) {
+ for (int i = 0; i < dpa_range_count; i++) {
+ if (validate_dpa_addr(ct3d,
+ media_op_in_pl->dpa_range_list[i].starting_dpa,
+ media_op_in_pl->dpa_range_list[i].length)) {
+ return CXL_MBOX_INVALID_INPUT;
+ }
+ total_mem += media_op_in_pl->dpa_range_list[i].length;
+ }
+ ct3d->media_op_sanitize = g_malloc0(sizeof(struct CXLSanitizeInfo) +
+ (dpa_range_count *
+ sizeof(struct dpa_range_list_entry)));
+
+ if (ct3d->media_op_sanitize) {
+ ct3d->media_op_sanitize->dpa_range_count = dpa_range_count;
+ ct3d->media_op_sanitize->fill_value = fill_value;
+ memcpy(ct3d->media_op_sanitize->dpa_range_list,
+ media_op_in_pl->dpa_range_list,
+ (dpa_range_count *
+ sizeof(struct dpa_range_list_entry)));
+ secs = get_sanitize_duration(total_mem >> 20);
+ goto start_bg;
+ }
+ } else if (dpa_range_count == 0) {
+ goto exit;
+ }
+
+start_bg:
+ /* EBUSY other bg cmds as of now */
+ cci->bg.runtime = secs * 1000UL;
+ *len_out = 0;
+ /* sanitize when done */
+ cxl_dev_disable_media(&ct3d->cxl_dstate);
+ return CXL_MBOX_BG_STARTED;
+exit:
return CXL_MBOX_SUCCESS;
}
@@ -3154,6 +3348,13 @@ static void bg_timercb(void *opaque)
cxl_dev_enable_media(&ct3d->cxl_dstate);
}
break;
+ case 0x4402: /* Media Operations sanitize */
+ {
+ CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
+ __do_sanitize(ct3d);
+ cxl_dev_enable_media(&ct3d->cxl_dstate);
+ }
+ break;
case 0x4304: /* scan media */
{
CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index a64739be25..6d82eb266a 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -581,6 +581,15 @@ typedef struct CXLSetFeatureInfo {
size_t data_size;
} CXLSetFeatureInfo;
+struct CXLSanitizeInfo {
+ uint32_t dpa_range_count;
+ uint8_t fill_value;
+ struct {
+ uint64_t starting_dpa;
+ uint64_t length;
+ } dpa_range_list[0];
+};
+
struct CXLType3Dev {
/* Private */
PCIDevice parent_obj;
@@ -651,6 +660,8 @@ struct CXLType3Dev {
uint8_t num_regions; /* 0-8 regions */
CXLDCRegion regions[DCD_MAX_NUM_REGION];
} dc;
+
+ struct CXLSanitizeInfo *media_op_sanitize;
};
#define TYPE_CXL_TYPE3 "cxl-type3"
--
2.34.1
- [PATCH 0/2] CXL CCI Media Operations, Vinayak Holikatti, 2025/01/23
- Message not available
- [PATCH 2/2] hw/cxl/cxl-mailbox-utils: Add support for Media operations Sanitize and Write Zeros commands (8.2.9.9.5.3),
Vinayak Holikatti <=
- Message not available