Add a new memory-backend-tagged supports a tag property where you can
find it based on tag. This is useful for scenarios where you want to add
a piece of memory for a particular purpose to be passed for another
device.
At the moment, this only supports a ram-backed object where we add a tag
to it, and it temporary. However, we are planning for a generalized
approach. The plan is to have a shim object where we add a tag to it,
and then it can be later linked to any BACKEND object types.
Example use QMP API:
{
"execute": "object-add",
"arguments": {
"qom-type": "memory-backend-tagged",
"id": "tm0",
"size": 1073741824,
"tag": "6be13bce-ae34-4a77-b6c3-16df975fcf1a"
}
}
Tags are assumed to be UUID. But this is something for debate maybe.
Signed-off-by: Alireza Sanaee <[email protected]>
---
hw/mem/meson.build | 1 +
hw/mem/tagged_mem.c | 116 ++++++++++++++++++++++++++++++++++++
include/hw/mem/tagged_mem.h | 31 ++++++++++
qapi/qom.json | 15 +++++
4 files changed, 163 insertions(+)
create mode 100644 hw/mem/tagged_mem.c
create mode 100644 include/hw/mem/tagged_mem.h
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
index 1c1c6da24b..529d86f840 100644
--- a/hw/mem/meson.build
+++ b/hw/mem/meson.build
@@ -10,3 +10,4 @@ system_ss.add(when: 'CONFIG_MEM_DEVICE', if_false:
files('memory-device-stubs.c'
system_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
system_ss.add(when: 'CONFIG_SPARSE_MEM', if_true: files('sparse-mem.c'))
+system_ss.add(files('tagged_mem.c'))
diff --git a/hw/mem/tagged_mem.c b/hw/mem/tagged_mem.c
new file mode 100644
index 0000000000..27b88e845e
--- /dev/null
+++ b/hw/mem/tagged_mem.c
@@ -0,0 +1,116 @@
+/*
+ * Tagged memory backend. Temporary implementation for testing purposes and
+ * only supports RAM based.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/mem/tagged_mem.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "qom/qom-qobject.h"
+
+static int check_property_equals_test(Object *obj, void *opaque)
+{
+ Error *err = NULL;
+ struct TagSearchContext *ctx = opaque;
+ g_autofree char *value;
+
+ if (!object_dynamic_cast(OBJECT(obj), TYPE_MEMORY_BACKEND_TAGGED)) {
+ return 0;
+ }
+
+ value = object_property_get_str(obj, "tag", &err);
+ if (err) {
+ error_report_err(err);
+ return 0;
+ }
+
+ if (strcmp(value, ctx->tag_value) == 0) {
+ ctx->result = MEMORY_BACKEND(obj);
+ return 1;
+ }
+
+ return 0;
+}
+
+HostMemoryBackend *memory_backend_tagged_find_by_tag(const char *tag,
+ Error **errp)
+{
+ struct TagSearchContext ctx = {
+ .tag_value = tag,
+ .result = NULL,
+ };
+
+ object_child_foreach_recursive(object_get_objects_root(),
+ check_property_equals_test, &ctx);
+
+ if (!ctx.result) {
+ qemu_log("didn't find any results!\n");
+ return NULL;
+ }
+
+ return ctx.result;
+}
+
+static void tagged_mem_set_tag(Object *obj, const char *value, Error **errp)
+{
+ MemoryBackendTagged *tm = MEMORY_BACKEND_TAGGED(obj);
+ g_free(tm->tag);
+ tm->tag = g_strdup(value);
+}
+
+static char *tagged_mem_get_tag(Object *obj, Error **errp)
+{
+ MemoryBackendTagged *tm = MEMORY_BACKEND_TAGGED(obj);
+ return g_strdup(tm->tag);
+}
+
+static bool ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
+{
+ g_autofree char *name = NULL;
+ uint32_t ram_flags;
+
+ if (!backend->size) {
+ error_setg(errp, "can't create backend with size 0");
+ return false;
+ }
+
+ name = host_memory_backend_get_name(backend);
+ ram_flags = backend->share ? RAM_SHARED : RAM_PRIVATE;
+ ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
+ return memory_region_init_ram_flags_nomigrate(
+ &backend->mr, OBJECT(backend), name, backend->size, ram_flags, errp);
+}
+
+static void memory_backend_tagged_class_init(ObjectClass *oc, const void *data)
+{
+ HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
+
+ bc->alloc = ram_backend_memory_alloc;
+ object_class_property_add_str(oc, "tag", tagged_mem_get_tag,
+ tagged_mem_set_tag);
+ object_class_property_set_description(oc, "tag",
+ "A user-defined tag to identify this memory backend");
+}
+
+static const TypeInfo memory_backend_tagged_info = {
+ .name = TYPE_MEMORY_BACKEND_TAGGED,
+ .parent = TYPE_MEMORY_BACKEND,
+ .instance_size = sizeof(MemoryBackendTagged),
+ .class_init = memory_backend_tagged_class_init,
+};
+
+static void memory_backend_tagged_register_types(void)
+{
+ type_register_static(&memory_backend_tagged_info);
+}
+
+type_init(memory_backend_tagged_register_types);
diff --git a/include/hw/mem/tagged_mem.h b/include/hw/mem/tagged_mem.h
new file mode 100644
index 0000000000..4f3b033597
--- /dev/null
+++ b/include/hw/mem/tagged_mem.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Tagged Memory backend
+ *
+ * Copyright (c) 2025 Alireza Sanaee <[email protected]>
+ */
+#ifndef HW_TAGGED_MEM_H
+#define HW_TAGGED_MEM_H
+
+#include "hw/qdev-core.h"
+#include "system/memory.h"
+#include "system/hostmem.h"
+
+#define TYPE_MEMORY_BACKEND_TAGGED "memory-backend-tagged"
+OBJECT_DECLARE_SIMPLE_TYPE(MemoryBackendTagged, MEMORY_BACKEND_TAGGED)
+
+typedef struct MemoryBackendTagged {
+ HostMemoryBackend parent_obj;
+
+ char *tag;
+} MemoryBackendTagged;
+
+struct TagSearchContext {
+ const char *tag_value;
+ HostMemoryBackend *result;
+};
+
+HostMemoryBackend *memory_backend_tagged_find_by_tag(const char *tag,
+ Error **errp);
+
+#endif
diff --git a/qapi/qom.json b/qapi/qom.json
index 830cb2ffe7..96d0184864 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -687,6 +687,19 @@
'size': 'size',
'*x-use-canonical-path-for-ramblock-id': 'bool' } }
+##
+# @MemoryBackendTaggedProperties:
+#
+# Properties for objects of classes derived from memory-backend.
+#
+# @tag: Memory tag
+#
+# Since: 11.0
+##
+{ 'struct': 'MemoryBackendTaggedProperties',
+ 'base': 'MemoryBackendProperties',
+ 'data': { '*tag': 'str' } }
+
##
# @MemoryBackendFileProperties:
#
@@ -1218,6 +1231,7 @@
{ 'name': 'memory-backend-memfd',
'if': 'CONFIG_LINUX' },
'memory-backend-ram',
+ 'memory-backend-tagged',
{ 'name': 'memory-backend-shm',
'if': 'CONFIG_POSIX' },
'pef-guest',
@@ -1296,6 +1310,7 @@
'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties',
'if': 'CONFIG_LINUX' },
'memory-backend-ram': 'MemoryBackendProperties',
+ 'memory-backend-tagged': 'MemoryBackendTaggedProperties',
'memory-backend-shm': { 'type': 'MemoryBackendShmProperties',
'if': 'CONFIG_POSIX' },
'pr-manager-helper': { 'type': 'PrManagerHelperProperties',
--
2.43.0