Add tag based removal, in which alias tear down must be done properly.
Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
---
hw/mem/cxl_type3.c | 119 +++++++++++++++++++++++++++++++++++++++++++++
qapi/cxl.json | 46 ++++++++++++++++++
2 files changed, 165 insertions(+)
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index d3ea62ef3f..29355792da 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -2186,6 +2186,61 @@ void qmp_cxl_add_dynamic_capacity(const char *path, uint16_t host_id,
}
}
+static void qmp_cxl_process_dynamic_capacity_tag_based(const char *path,
+ uint16_t hid, CXLDCEventType type, uint8_t rid, const char *tag,
+ CxlDynamicCapacityExtentList *records, Error **errp) {
+
+ Object *obj;
+ CXLType3Dev *dcd;
+ CXLDCExtentList *list = NULL;
+ CXLDCExtent *ent;
+ g_autofree CXLDCExtentRaw *extents = NULL;
+
+ obj = object_resolve_path_type(path, TYPE_CXL_TYPE3, NULL);
+ if (!obj) {
+ error_setg(errp, "Unable to resolve CXL type 3 device");
+ return;
+ }
+
+ dcd = CXL_TYPE3(obj);
+ if (!dcd->dc.num_regions) {
+ error_setg(errp, "No dynamic capacity support from the device");
+ return;
+ }
+
+ if (rid >= dcd->dc.num_regions) {
+ error_setg(errp, "region id is too large");
+ return;
+ }
+
+ QemuUUID uuid_req;
+ qemu_uuid_parse(tag, &uuid_req);
+
+ list = &dcd->dc.extents;
+ size_t cap = 8, n = 0;
+ extents = g_new0(CXLDCExtentRaw, cap);
+ QTAILQ_FOREACH(ent, list, node) {
+ QemuUUID uuid_ext;
+ memcpy(&uuid_ext.data, ent->tag, sizeof(ent->tag));
+ if (!qemu_uuid_is_equal(&uuid_req, &uuid_ext)) {
+ continue;
+ }
+
+ if (n == cap) {
+ cap = cap < 8 ? 8 : cap * 2;
+ extents = g_renew(CXLDCExtentRaw, extents, cap);
+ }
+
+ extents[n++] = (CXLDCExtentRaw){ .start_dpa = ent->start_dpa,
+ .len = ent->len,
+ .shared_seq = 0 };
+ }
+
+ extents = g_renew(CXLDCExtentRaw, extents, n);
+ cxl_create_dc_event_records_for_extents(dcd, type, extents, n);
+ return;
+}
+
void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id,
CxlExtentRemovalPolicy removal_policy,
bool has_forced_removal,
@@ -2212,6 +2267,10 @@ void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id,
region, tag, extents,
errp);
return;
+ case CXL_EXTENT_REMOVAL_POLICY_TAG_BASED:
+ qmp_cxl_process_dynamic_capacity_tag_based(path, host_id, type, region,
+ tag, extents, errp);
+ return;
default:
error_setg(errp, "Removal policy not supported");
return;
@@ -2241,6 +2300,66 @@ void cxl_remove_memory_alias(CXLType3Dev *dcd, struct CXLFixedWindow *fw,
return;
}
+/*
+ * This function allows for a simple check to make sure that
+ * our extent is removed. It can be used by an orchestration layer.
+ */
+ExtentStatus *qmp_cxl_release_dynamic_capacity_status(const char *path,
+ uint16_t hid, uint8_t rid,
+ const char *tag,
+ Error **errp)
+{
+ Object *obj;
+ CXLType3Dev *dcd;
+ CXLDCExtentList *list = NULL;
+ CXLDCExtent *ent;
+ QemuUUID uuid_req;
+ ExtentStatus *res = g_new0(ExtentStatus, 1);
+
+ obj = object_resolve_path_type(path, TYPE_CXL_TYPE3, NULL);
+ if (!obj) {
+ error_setg(errp, "Unable to resolve CXL type 3 device");
+ return NULL;
+ }
+
+ dcd = CXL_TYPE3(obj);
+ if (!dcd->dc.num_regions) {
+ error_setg(errp, "No dynamic capacity support from the device");
+ return NULL;
+ }
+
+ if (rid >= dcd->dc.num_regions) {
+ error_setg(errp, "Region id is too large");
+ return NULL;
+ }
+
+ if (!tag) {
+ error_setg(errp, "Tag must be valid");
+ return NULL;
+ }
+
+ list = &dcd->dc.extents;
+ qemu_uuid_parse(tag, &uuid_req);
+
+ QTAILQ_FOREACH(ent, list, node) {
+ QemuUUID uuid_ext;
+ memcpy(&uuid_ext.data, ent->tag, sizeof(ent->tag));
+ if (qemu_uuid_is_equal(&uuid_req, &uuid_ext) == true) {
+ res->status = g_strdup("Not Released");
+ res->message =
+ g_strdup_printf("Found extent with tag %s dpa 0x%" PRIx64
+ " len 0x%" PRIx64 "\n",
+ ent->tag, ent->start_dpa, ent->len);
+ return res;
+ }
+ }
+
+
+ res->status = g_strdup("Released");
+ res->message = g_strdup_printf("Tag %s released or not found\n", tag);
+ return res;
+}
+
static void ct3_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
diff --git a/qapi/cxl.json b/qapi/cxl.json
index 52cc5d4f33..3372ce3745 100644
--- a/qapi/cxl.json
+++ b/qapi/cxl.json
@@ -555,3 +555,49 @@
},
'features': [ 'unstable' ]
}
+
+##
+# @ExtentStatus:
+# This is an object that describes the status of an extent.
+#
+# @status: String indicating the overall result, e.g. "success".
+# @message: Human-readable description of the outcome.
+#
+# Since: 9.1
+##
+{ 'struct': 'ExtentStatus',
+ 'data': { 'status': 'str', 'message': 'str' }
+}
+
+##
+# @cxl-release-dynamic-capacity-status:
+#
+# This commands checks if an extent tag has been released or not.
+#
+# @path: path to the CXL Dynamic Capacity Device in the QOM tree.
+#
+# @host-id: The "Host ID" field as defined in Compute Express Link
+# (CXL) Specification, Revision 3.1, Table 7-71.
+#
+# @region: The "Region Number" field as defined in Compute Express
+# Link Specification, Revision 3.1, Table 7-71. Valid range
+# is from 0-7.
+#
+# @tag: The "Tag" field as defined in Compute Express Link (CXL)
+# Specification, Revision 3.1, Table 7-71.
+#
+# Features:
+#
+# @unstable: For now this command is subject to change.
+#
+# Since: 9.1
+##
+{ 'command': 'cxl-release-dynamic-capacity-status',
+ 'data': { 'path': 'str',
+ 'host-id': 'uint16',
+ 'region': 'uint8',
+ 'tag': 'str'
+ },
+ 'features': [ 'unstable' ],
+ 'returns': 'ExtentStatus'
+}
--
2.43.0
© 2016 - 2025 Red Hat, Inc.