When a type3 device is created with dc-regions-total-size instead of an
initial volatile-dc-memdev, prescriptive DC add requests need a way to name
the backend to attach to the accepted extent.
Teach the QMP and mailbox paths to carry that tag through the lazy
dynamic-capacity flow. In the add path, resolve the tag to a generic host
memory backend, reject reuse of an already-mapped backend, and verify that
the backend size matches the requested extent.
Store the selected backend metadata on the pending extent so a later patch
can bind the accepted extent to the chosen backend when the host
acknowledges the request.
Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
---
hw/cxl/cxl-mailbox-utils.c | 8 ----
hw/mem/cxl_type3.c | 77 ++++++++++++++++++++++++++++++++------
2 files changed, 65 insertions(+), 20 deletions(-)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index e6e136cf44..c83b5f90d4 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -4270,10 +4270,6 @@ static CXLRetCode cmd_fm_initiate_dc_add(const struct cxl_cmd *cmd,
CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
int i, rc;
- if (ct3d->dc.total_capacity_cmd) {
- return CXL_MBOX_UNSUPPORTED;
- }
-
switch (in->selection_policy) {
case CXL_EXTENT_SELECTION_POLICY_PRESCRIPTIVE: {
/* Adding extents exceeds device's extent tracking ability. */
@@ -4361,10 +4357,6 @@ static CXLRetCode cmd_fm_initiate_dc_release(const struct cxl_cmd *cmd,
CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
int i, rc;
- if (ct3d->dc.total_capacity_cmd) {
- return CXL_MBOX_UNSUPPORTED;
- }
-
switch (in->flags & CXL_EXTENT_REMOVAL_POLICY_MASK) {
case CXL_EXTENT_REMOVAL_POLICY_PRESCRIPTIVE: {
CXLDCExtentList updated_list;
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 45fb6c55bc..569184975f 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -30,6 +30,7 @@
#include "system/numa.h"
#include "hw/cxl/cxl.h"
#include "hw/pci/msix.h"
+#include "qemu/uuid.h"
/* type3 device private */
enum CXL_T3_MSIX_VECTOR {
@@ -2289,13 +2290,42 @@ bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list,
return false;
}
+static bool cxl_device_lazy_dynamic_capacity_init(CXLType3Dev *ct3d,
+ const char *tag,
+ Error **errp)
+{
+ MemoryRegion *dc_mr;
+
+ ct3d->dc.host_dc = host_memory_backend_find_by_tag(tag);
+ if (!ct3d->dc.host_dc) {
+ error_setg(errp, "dynamic capacity must have a backing device");
+ return false;
+ }
+
+ dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc);
+ if (!dc_mr) {
+ error_setg(errp, "dynamic capacity must have a backing device");
+ return false;
+ }
+
+ if (host_memory_backend_is_mapped(ct3d->dc.host_dc)) {
+ error_setg(errp,
+ "memory backend %s is already mapped and cannot be reused",
+ object_get_canonical_path_component(
+ OBJECT(ct3d->dc.host_dc)));
+ return false;
+ }
+
+ return true;
+}
+
/*
* The main function to process dynamic capacity event with extent list.
* Currently DC extents add/release requests are processed.
*/
static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
uint16_t hid, CXLDCEventType type, uint8_t rid,
- CxlDynamicCapacityExtentList *records, Error **errp)
+ const char *tag, CxlDynamicCapacityExtentList *records, Error **errp)
{
Object *obj;
CXLType3Dev *dcd;
@@ -2303,7 +2333,8 @@ static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
CxlDynamicCapacityExtentList *list;
CXLDCExtentGroup *group = NULL;
g_autofree CXLDCExtentRaw *extents = NULL;
- uint64_t dpa, offset, len, block_size;
+ uint64_t dpa, offset, block_size;
+ uint64_t len = 0;
g_autofree unsigned long *blk_bitmap = NULL;
int i;
@@ -2319,13 +2350,6 @@ static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
return;
}
- if (dcd->dc.total_capacity_cmd) {
- error_setg(errp,
- "dc-regions-total-size is set: extent add/release via QMP "
- "not yet supported without a backing device at init");
- return;
- }
-
if (rid >= dcd->dc.num_regions) {
error_setg(errp, "region id is too large");
return;
@@ -2334,6 +2358,8 @@ static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
blk_bitmap = bitmap_new(dcd->dc.regions[rid].len / block_size);
/* Sanity check and count the extents */
+ QemuUUID uuid;
+ qemu_uuid_parse(tag, &uuid);
list = records;
while (list) {
offset = list->value->offset;
@@ -2392,6 +2418,31 @@ static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
num_extents++;
}
+ if (type == DC_EVENT_ADD_CAPACITY && dcd->dc.total_capacity_cmd) {
+ MemoryRegion *host_dc_mr;
+ uint64_t size;
+
+ if (num_extents > 1) {
+ error_setg(errp, "Only single extent add is supported currently");
+ return;
+ }
+
+ if (!cxl_device_lazy_dynamic_capacity_init(dcd, tag, errp)) {
+ return;
+ }
+
+ host_dc_mr = host_memory_backend_get_memory(dcd->dc.host_dc);
+ size = memory_region_size(host_dc_mr);
+
+ if (size != len) {
+ error_setg(errp,
+ "Host memory backend size 0x%" PRIx64
+ " does not match extent length 0x%" PRIx64,
+ size, len);
+ return;
+ }
+ }
+
/* Create extent list for event being passed to host */
i = 0;
list = records;
@@ -2403,7 +2454,7 @@ static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path,
extents[i].start_dpa = dpa;
extents[i].len = len;
- memset(extents[i].tag, 0, 0x10);
+ memcpy(extents[i].tag, &uuid.data, 0x10);
extents[i].shared_seq = 0;
if (type == DC_EVENT_ADD_CAPACITY) {
group = cxl_insert_extent_to_extent_group(group,
@@ -2434,7 +2485,8 @@ void qmp_cxl_add_dynamic_capacity(const char *path, uint16_t host_id,
case CXL_EXTENT_SELECTION_POLICY_PRESCRIPTIVE:
qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id,
DC_EVENT_ADD_CAPACITY,
- region, extents, errp);
+ region, tag,
+ extents, errp);
return;
default:
error_setg(errp, "Selection policy not supported");
@@ -2465,7 +2517,8 @@ void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id,
switch (removal_policy) {
case CXL_EXTENT_REMOVAL_POLICY_PRESCRIPTIVE:
qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id, type,
- region, extents, errp);
+ region, tag,
+ extents, errp);
return;
default:
error_setg(errp, "Removal policy not supported");
--
2.50.1 (Apple Git-155)
© 2016 - 2026 Red Hat, Inc.