From: "Ho-Ren (Jack) Chuang" <horenchuang@bytedance.com>
To: "Michael S. Tsirkin" <mst@redhat.com>,
"Hao Xiang" <hao.xiang@bytedance.com>,
"Jonathan Cameron" <Jonathan.Cameron@huawei.com>,
"Ben Widawsky" <ben.widawsky@intel.com>,
"Gregory Price" <gourry.memverge@gmail.com>,
"Fan Ni" <fan.ni@samsung.com>, "Ira Weiny" <ira.weiny@intel.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"David Hildenbrand" <david@redhat.com>,
"Igor Mammedov" <imammedo@redhat.com>,
"Eric Blake" <eblake@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Daniel P. Berrangé" <berrange@redhat.com>,
"Eduardo Habkost" <eduardo@habkost.net>,
qemu-devel@nongnu.org
Cc: "Ho-Ren (Jack) Chuang" <horenc@vt.edu>,
"Ho-Ren (Jack) Chuang" <horenchuang@bytedance.com>,
linux-cxl@vger.kernel.org
Subject: [QEMU-devel][RFC PATCH 1/1] backends/hostmem: qapi/qom: Add an ObjectOption for memory-backend-* called HostMemType and its arg 'cxlram'
Date: Sun, 31 Dec 2023 23:53:15 -0800 [thread overview]
Message-ID: <20240101075315.43167-2-horenchuang@bytedance.com> (raw)
In-Reply-To: <20240101075315.43167-1-horenchuang@bytedance.com>
Introduce a new configuration option 'host-mem-type=' in the
'-object memory-backend-ram', allowing users to specify
from which type of memory to allocate.
Users can specify 'cxlram' as an argument, and QEMU will then
automatically locate CXL RAM NUMA nodes and use them as the backend memory.
For example:
-object memory-backend-ram,id=vmem0,size=19G,host-mem-type=cxlram \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1 \
-device cxl-rp,port=0,bus=cxl.1,id=root_port13,chassis=0,slot=2 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0 \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=19G,cxl-fmw.0.interleave-granularity=8k \
In v1, we plan to move most of the implementations to util and break down
this patch into different smaller patches.
Signed-off-by: Ho-Ren (Jack) Chuang <horenchuang@bytedance.com>
Signed-off-by: Hao Xiang <hao.xiang@bytedance.com>
---
backends/hostmem.c | 184 +++++++++++++++++++++++++++++++++++++++
include/sysemu/hostmem.h | 1 +
qapi/common.json | 19 ++++
qapi/qom.json | 1 +
qemu-options.hx | 2 +-
5 files changed, 206 insertions(+), 1 deletion(-)
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 747e7838c0..3bede13879 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -44,6 +44,133 @@ host_memory_backend_get_name(HostMemoryBackend *backend)
return object_get_canonical_path(OBJECT(backend));
}
+#define FILE_LINE_LEN 256
+static int
+is_valid_node(const char *path) {
+ FILE *file = fopen(path, "r");
+ if (file == NULL) {
+ return -1;
+ }
+
+ char line[FILE_LINE_LEN];
+ if (fgets(line, sizeof(line), file) != NULL) {
+ int target_node = atoi(line);
+
+ if (target_node >= 0) {
+ fclose(file);
+ return target_node;
+ }
+ }
+
+ fclose(file);
+ return -1;
+}
+
+static int
+is_directory(const char *path) {
+ struct stat path_stat;
+ stat(path, &path_stat);
+ return S_ISDIR(path_stat.st_mode);
+}
+
+static int
+is_symlink(const char *path) {
+ struct stat path_stat;
+ if (lstat(path, &path_stat) == -1) {
+ return 0;
+ }
+ return S_ISLNK(path_stat.st_mode);
+}
+
+#define CXL_DEVICE_PATH "/sys/bus/cxl/devices/"
+#define REGION_PATH_LEN 307
+#define DAX_REGION_PATH_LEN 563
+#define DAX_PATH_LEN 819
+#define TARGET_FILE_PATH_LEN 831
+/*
+ * return: the number of valid numa node id found
+ */
+static int
+host_memory_backend_get_cxlram_nodes(int *valid_cxlram_nodes) {
+ DIR *base_dir = NULL, *region_dir = NULL, *dax_region_dir = NULL;
+ const char *base_dir_path = CXL_DEVICE_PATH;
+ struct dirent *entry;
+ int valid_node = 0, ret = 0;
+
+ base_dir = opendir(base_dir_path);
+ if (base_dir == NULL) {
+ return valid_node;
+ }
+
+ while ((entry = readdir(base_dir)) != NULL) {
+ char region_path[REGION_PATH_LEN];
+
+ ret = snprintf(region_path, sizeof(region_path), "%s%s",
+ base_dir_path, entry->d_name);
+ if (ret < 0 ||
+ !is_symlink(region_path) ||
+ strncmp(entry->d_name, "region", ARRAY_SIZE("region") - 1)) {
+ continue;
+ }
+
+ region_dir = opendir(region_path);
+ if (region_dir == NULL) {
+ goto region_exit;
+ }
+
+ while ((entry = readdir(region_dir)) != NULL) {
+ char dax_region_path[DAX_REGION_PATH_LEN];
+
+ ret = snprintf(dax_region_path, sizeof(dax_region_path), "%s/%s",
+ region_path, entry->d_name);
+ if (ret < 0 ||
+ !is_directory(dax_region_path) ||
+ strncmp(entry->d_name, "dax_region",
+ ARRAY_SIZE("dax_region") - 1)) {
+
+ continue;
+ }
+
+ dax_region_dir = opendir(dax_region_path);
+ if (dax_region_dir == NULL) {
+ goto dax_region_exit;
+ }
+
+ while ((entry = readdir(dax_region_dir)) != NULL) {
+ int target_node;
+ char dax_path[DAX_PATH_LEN];
+ char target_file_path[TARGET_FILE_PATH_LEN];
+ ret = snprintf(dax_path, sizeof(dax_path), "%s/%s",
+ dax_region_path, entry->d_name);
+ if (ret < 0 ||
+ !is_directory(dax_path) ||
+ strncmp(entry->d_name, "dax", ARRAY_SIZE("dax") - 1)) {
+ continue;
+ }
+
+ ret = snprintf(target_file_path, sizeof(target_file_path),
+ "%s/target_node", dax_path);
+ if (ret < 0) {
+ continue;
+ }
+
+ target_node = is_valid_node(target_file_path);
+ if (target_node >= 0) {
+ valid_cxlram_nodes[valid_node] = target_node;
+ valid_node++;
+ }
+ }
+ }
+ }
+
+ closedir(dax_region_dir);
+dax_region_exit:
+ closedir(region_dir);
+region_exit:
+ closedir(base_dir);
+ return valid_node;
+}
+
static void
host_memory_backend_get_size(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
@@ -117,6 +244,12 @@ host_memory_backend_set_host_nodes(Object *obj, Visitor *v, const char *name,
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
uint16List *l, *host_nodes = NULL;
+ if (backend->host_mem_type == HOST_MEM_TYPE_CXLRAM) {
+ error_setg(errp,
+ "'host-mem-type=' and 'host-nodes='/'policy=' are incompatible");
+ return;
+ }
+
visit_type_uint16List(v, name, &host_nodes, errp);
for (l = host_nodes; l; l = l->next) {
@@ -150,6 +283,11 @@ host_memory_backend_set_policy(Object *obj, int policy, Error **errp)
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
backend->policy = policy;
+ if (backend->host_mem_type == HOST_MEM_TYPE_CXLRAM) {
+ error_setg(errp,
+ "'host-mem-type=' and 'host-nodes='/'policy=' are incompatible");
+ }
+
#ifndef CONFIG_NUMA
if (policy != HOST_MEM_POLICY_DEFAULT) {
error_setg(errp, "NUMA policies are not supported by this QEMU");
@@ -157,6 +295,46 @@ host_memory_backend_set_policy(Object *obj, int policy, Error **errp)
#endif
}
+static int
+host_memory_backend_get_host_mem_type(Object *obj, Error **errp G_GNUC_UNUSED)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ return backend->host_mem_type;
+}
+
+static void
+host_memory_backend_set_host_mem_type(Object *obj, int host_mem_type, Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ backend->host_mem_type = host_mem_type;
+
+#ifndef CONFIG_NUMA
+ error_setg(errp, "NUMA node host memory types are not supported by this QEMU");
+#else
+ int i, valid_cxlram_nodes[MAX_NODES];
+
+ if (backend->policy > 0 ||
+ !bitmap_empty(backend->host_nodes, MAX_NODES)) {
+ error_setg(errp,
+ "'host-mem-type=' and 'host-nodes='/'policy=' are incompatible");
+ return;
+ }
+
+ if (host_memory_backend_get_cxlram_nodes(valid_cxlram_nodes) > 0) {
+ for (i = 0; i < MAX_NODES; i++) {
+ if (valid_cxlram_nodes[i] < 0) {
+ break;
+ }
+ bitmap_set(backend->host_nodes, valid_cxlram_nodes[i], 1);
+ }
+ } else {
+ error_setg(errp, "Cannot find CXL RAM on host");
+ return;
+ }
+ backend->policy = HOST_MEM_POLICY_BIND;
+#endif
+}
+
static bool host_memory_backend_get_merge(Object *obj, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
@@ -536,6 +714,12 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
host_memory_backend_get_share, host_memory_backend_set_share);
object_class_property_set_description(oc, "share",
"Mark the memory as private to QEMU or shared");
+ object_class_property_add_enum(oc, "host-mem-type", "HostMemType",
+ &HostMemType_lookup,
+ host_memory_backend_get_host_mem_type,
+ host_memory_backend_set_host_mem_type);
+ object_class_property_set_description(oc, "host-mem-type",
+ "Set the backend host memory type");
#ifdef CONFIG_LINUX
object_class_property_add_bool(oc, "reserve",
host_memory_backend_get_reserve, host_memory_backend_set_reserve);
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index 39326f1d4f..afeb9b71d1 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -70,6 +70,7 @@ struct HostMemoryBackend {
ThreadContext *prealloc_context;
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
HostMemPolicy policy;
+ HostMemType host_mem_type;
MemoryRegion mr;
};
diff --git a/qapi/common.json b/qapi/common.json
index 6fed9cde1a..591fd73291 100644
--- a/qapi/common.json
+++ b/qapi/common.json
@@ -167,6 +167,25 @@
{ 'enum': 'HostMemPolicy',
'data': [ 'default', 'preferred', 'bind', 'interleave' ] }
+##
+# @HostMemType:
+#
+# Automatically find a backend memory type on host.
+# Can be further extened to support other types such as cxlpmem, hbm.
+#
+# @none: do nothing (default).
+#
+# @cxlram: a CXL RAM backend on host.
+#
+# Note: HostMemType and HostMemPolicy/host-nodes cannot be set at the same
+# time. HostMemType is used to automatically bind with one kind of
+# host memory types.
+#
+# Since: 8.3
+##
+{ 'enum': 'HostMemType',
+ 'data': [ 'none', 'cxlram' ] }
+
##
# @NetFilterDirection:
#
diff --git a/qapi/qom.json b/qapi/qom.json
index 95516ba325..fa3bc29708 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -626,6 +626,7 @@
'*host-nodes': ['uint16'],
'*merge': 'bool',
'*policy': 'HostMemPolicy',
+ '*host-mem-type': 'HostMemType',
'*prealloc': 'bool',
'*prealloc-threads': 'uint32',
'*prealloc-context': 'str',
diff --git a/qemu-options.hx b/qemu-options.hx
index b66570ae00..39074c1aa0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -5211,7 +5211,7 @@ SRST
(``share=off``). For this use case, we need writable RAM instead
of ROM, and want to also set ``rom=off``.
- ``-object memory-backend-ram,id=id,merge=on|off,dump=on|off,share=on|off,prealloc=on|off,size=size,host-nodes=host-nodes,policy=default|preferred|bind|interleave``
+ ``-object memory-backend-ram,id=id,merge=on|off,dump=on|off,share=on|off,prealloc=on|off,size=size,host-mem-type=cxlram,host-nodes=host-nodes,policy=default|preferred|bind|interleave``
Creates a memory backend object, which can be used to back the
guest RAM. Memory backend objects offer more control than the
``-m`` option that is traditionally used to define guest RAM.
--
Regards,
Hao Xiang and Ho-Ren (Jack) Chuang
next prev parent reply other threads:[~2024-01-01 7:53 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-01 7:53 [QEMU-devel][RFC PATCH 0/1] Introduce HostMemType for 'memory-backend-*' Ho-Ren (Jack) Chuang
2024-01-01 7:53 ` Ho-Ren (Jack) Chuang [this message]
2024-01-02 10:29 ` [QEMU-devel][RFC PATCH 1/1] backends/hostmem: qapi/qom: Add an ObjectOption for memory-backend-* called HostMemType and its arg 'cxlram' Philippe Mathieu-Daudé
2024-01-02 13:03 ` David Hildenbrand
2024-01-06 0:45 ` [External] " Hao Xiang
2024-01-03 21:56 ` Gregory Price
2024-01-06 5:59 ` [External] " Hao Xiang
2024-01-08 17:15 ` Gregory Price
2024-01-08 22:47 ` Hao Xiang
2024-01-09 1:05 ` Hao Xiang
2024-01-09 1:13 ` Gregory Price
2024-01-09 19:33 ` Hao Xiang
2024-01-09 19:57 ` Gregory Price
2024-01-09 21:27 ` Hao Xiang
2024-01-09 22:13 ` Gregory Price
2024-01-09 23:55 ` Hao Xiang
2024-01-10 14:31 ` Jonathan Cameron
2024-01-12 15:32 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240101075315.43167-2-horenchuang@bytedance.com \
--to=horenchuang@bytedance.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=armbru@redhat.com \
--cc=ben.widawsky@intel.com \
--cc=berrange@redhat.com \
--cc=david@redhat.com \
--cc=eblake@redhat.com \
--cc=eduardo@habkost.net \
--cc=fan.ni@samsung.com \
--cc=gourry.memverge@gmail.com \
--cc=hao.xiang@bytedance.com \
--cc=horenc@vt.edu \
--cc=imammedo@redhat.com \
--cc=ira.weiny@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox