From 4f3cd4eb05cd64ce365592704395af5ff394da70 Mon Sep 17 00:00:00 2001 From: zhangpengrui Date: Wed, 12 Nov 2025 10:51:02 +0800 Subject: [PATCH] iQEMU update to version 8.2.0-52 Signed-off-by: zhangpengrui --- ...port-of-one-guest-numa-node-alloc-me.patch | 288 ++++++++++++++++++ qemu.spec | 8 +- ...race-to-measure-hot-migrate-downtime.patch | 47 +++ 3 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 backends-Add-support-of-one-guest-numa-node-alloc-me.patch create mode 100644 trace-Add-trace-to-measure-hot-migrate-downtime.patch diff --git a/backends-Add-support-of-one-guest-numa-node-alloc-me.patch b/backends-Add-support-of-one-guest-numa-node-alloc-me.patch new file mode 100644 index 00000000..18d1220b --- /dev/null +++ b/backends-Add-support-of-one-guest-numa-node-alloc-me.patch @@ -0,0 +1,288 @@ +From 9c887818bbb38d8efb89af37d991c5910fb878aa Mon Sep 17 00:00:00 2001 +From: leizongkun +Date: Tue, 4 Nov 2025 12:01:14 +0800 +Subject: [PATCH] backends: Add support of one guest numa node alloc memory + from multi host nodes + +It provides QEMU with a more flexible memory NUMA binding approach, +allowing a guest NUMA node to allocate memory +to different host NUMA nodes according to specified proportions. + +Signed-off-by: wangzhigang +Signed-off-by: zhangliang +Signed-off-by: leizongkun +--- + backends/hostmem.c | 131 ++++++++++++++++++++++++++++++++++ + include/sysemu/hostmem.h | 3 + + meson.build | 8 +++ + meson_options.txt | 3 + + qapi/qom.json | 1 + + scripts/meson-buildoptions.sh | 5 ++ + 6 files changed, 151 insertions(+) + +diff --git a/backends/hostmem.c b/backends/hostmem.c +index 747e7838c0..9c5162760f 100644 +--- a/backends/hostmem.c ++++ b/backends/hostmem.c +@@ -20,6 +20,12 @@ + #include "qom/object_interfaces.h" + #include "qemu/mmap-alloc.h" + #include "qemu/madvise.h" ++#ifdef CONFIG_MBIND_PROPORTION ++#include "qemu/option.h" ++#include "sysemu/sysemu.h" ++#include "qemu/log.h" ++#include "qemu/units.h" ++#endif + + #ifdef CONFIG_NUMA + #include +@@ -32,6 +38,12 @@ QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_DEFAULT != MPOL_DEFAULT); + QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_PREFERRED != MPOL_PREFERRED); + QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_BIND != MPOL_BIND); + QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_INTERLEAVE != MPOL_INTERLEAVE); ++ ++#ifdef CONFIG_MBIND_PROPORTION ++#define PROPORTION_MAX_NUM 11 ++#define PER_PROPORTION_MAX_LENGTH 32 ++#define PROPORTION_MAX_LENGTH 512 ++#endif + #endif + + char * +@@ -137,6 +149,22 @@ out: + #endif + } + ++#ifdef CONFIG_MBIND_PROPORTION ++static void ++host_memory_backend_set_propertion(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++#ifdef CONFIG_NUMA ++ HostMemoryBackend *backend = MEMORY_BACKEND(obj); ++ char *pro; ++ visit_type_str(v, name, &pro, errp); ++ backend->propertion = pro; ++#else ++ error_setg(errp, "NUMA node binding are not supported by this QEMU"); ++#endif ++} ++#endif ++ + static int + host_memory_backend_get_policy(Object *obj, Error **errp G_GNUC_UNUSED) + { +@@ -319,6 +347,95 @@ size_t host_memory_backend_pagesize(HostMemoryBackend *memdev) + return pagesize; + } + ++#ifdef CONFIG_MBIND_PROPORTION ++static int mbind_by_proportions(void *ptr, const char *bind_proportions, uint64_t sz) ++{ ++ char proportion_str[PROPORTION_MAX_LENGTH]; ++ char proportions[PROPORTION_MAX_NUM][PER_PROPORTION_MAX_LENGTH]; ++ int proportions_num, i; ++ char *token; ++ uint64_t size = 0; ++ long mbind_ret = -1; ++ uint64_t size_total = 0; ++ ++ if (strlen(bind_proportions) >= PROPORTION_MAX_LENGTH) { ++ qemu_log("the lenth of bind_proportions is too long, max len is %d\n", PROPORTION_MAX_LENGTH); ++ return -1; ++ } ++ if (memcpy(proportion_str, bind_proportions, strlen(bind_proportions) + 1) == NULL) { ++ qemu_log("failed to copy bind_proportions\n"); ++ return -1; ++ } ++ proportions_num = 0; ++ token = strtok(proportion_str, ":"); ++ while (token != NULL) { ++ if (strlen(token) + 1 >= PER_PROPORTION_MAX_LENGTH ) { ++ qemu_log("bind_proportions token is too long, max len is %d\n", PER_PROPORTION_MAX_LENGTH); ++ return -1; ++ } ++ if (memcpy(proportions[proportions_num], token, strlen(token) + 1) == NULL) { ++ qemu_log("failed to copy token\n"); ++ return -1; ++ } ++ proportions_num++; ++ if (proportions_num >= PROPORTION_MAX_NUM) { ++ qemu_log("invalid proportions number, max is %d\n", PROPORTION_MAX_NUM); ++ return -1; ++ } ++ token = strtok(NULL, ":"); ++ } ++ ++ for (i = 0; i < proportions_num; i++) { ++ unsigned long tmp_lastbit, tmp_maxnode; ++ char prop[PROPORTION_MAX_LENGTH]; ++ char *end, *prop_token, *pos; ++ long int node_id; ++ long size_token; ++ DECLARE_BITMAP(tmp_host_nodes, MAX_NODES + 1) = {0}; ++ ++ ptr = (void*)((char*)ptr + size); ++ if (memcpy(prop, proportions[i], strlen(proportions[i]) + 1) == NULL) { ++ qemu_log("failed to copy propertion"); ++ return -1; ++ } ++ prop_token = strtok(prop, "-"); ++ if (prop_token == NULL) { ++ return -1; ++ } ++ size_token = strtol(prop_token, &end, 10); ++ if (*end != '\0') { ++ return -1; ++ } ++ size = size_token * MiB; ++ size_total += size; ++ prop_token = strtok(NULL, "-"); ++ pos = strstr(prop_token, "node"); ++ pos += strlen("node"); ++ node_id = strtol(pos, &end, 10); ++ if (*end != '\0') { ++ perror("failed to convert node_id from string to number"); ++ return -1; ++ } ++ bitmap_set(tmp_host_nodes, node_id, 1); ++ tmp_lastbit = find_last_bit(tmp_host_nodes, MAX_NODES); ++ tmp_maxnode = (tmp_lastbit + 1) % (MAX_NODES + 1); ++ qemu_log("mbind args: addr %p, size '%" PRIu64 "', node: %ld, \n", ptr, size, node_id); ++ mbind_ret = mbind(ptr, size, MPOL_BIND, tmp_host_nodes, tmp_maxnode + 1, ++ MPOL_MF_STRICT | MPOL_MF_MOVE); ++ if (mbind_ret < 0) { ++ perror("failed to mbind address to host node"); ++ return -1; ++ } ++ } ++ if (size_total != sz) { ++ qemu_log("invalid proportion config, length %" PRIu64 " is not same as " ++ "all tokens '%" PRIu64 "'", sz, size_total); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ + static void + host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) + { +@@ -352,6 +469,17 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) + * this doesn't catch hugepage case. */ + unsigned flags = MPOL_MF_STRICT | MPOL_MF_MOVE; + int mode = backend->policy; ++#ifdef CONFIG_MBIND_PROPORTION ++ const char *proportion = backend->propertion; ++ if (proportion != NULL) { ++ if (mbind_by_proportions(ptr, proportion, sz) < 0) { ++ error_setg(errp, "failed to mbind_by_proportions"); ++ return; ++ } ++ free(backend->propertion); ++ goto prealloc; ++ } ++#endif + + /* check for invalid host-nodes and policies and give more verbose + * error messages than mbind(). */ +@@ -398,6 +526,9 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) + * This is necessary to guarantee memory is allocated with + * specified NUMA policy in place. + */ ++#ifdef CONFIG_MBIND_PROPORTION ++prealloc: ++#endif + if (backend->prealloc) { + qemu_prealloc_mem(memory_region_get_fd(&backend->mr), ptr, sz, + backend->prealloc_threads, +diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h +index 39326f1d4f..83cb9e468d 100644 +--- a/include/sysemu/hostmem.h ++++ b/include/sysemu/hostmem.h +@@ -70,6 +70,9 @@ struct HostMemoryBackend { + ThreadContext *prealloc_context; + DECLARE_BITMAP(host_nodes, MAX_NODES + 1); + HostMemPolicy policy; ++#ifdef CONFIG_MBIND_PROPORTION ++ char *propertion; ++#endif + + MemoryRegion mr; + }; +diff --git a/meson.build b/meson.build +index 6a8410fabb..50b1e31edf 100644 +--- a/meson.build ++++ b/meson.build +@@ -566,6 +566,13 @@ have_tpm = get_option('tpm') \ + .require(targetos != 'windows', error_message: 'TPM emulation only available on POSIX systems') \ + .allowed() + ++# mbind_proportion ++have_mbind_proportion = get_option('mbind_by_proportion') \ ++ .require(targetos == 'linux', error_message: 'mbind_by_proportion is supported only on Linux') \ ++ .allowed() ++ ++config_host_data.set('CONFIG_MBIND_PROPORTION', have_mbind_proportion) ++ + # vhost + have_vhost_user = get_option('vhost_user') \ + .disable_auto_if(targetos != 'linux') \ +@@ -4487,6 +4494,7 @@ summary_info += {'libudev': libudev} + summary_info += {'FUSE lseek': fuse_lseek.found()} + summary_info += {'selinux': selinux} + summary_info += {'libdw': libdw} ++summary_info += {'mbind proportion': have_mbind_proportion} + summary(summary_info, bool_yn: true, section: 'Dependencies') + + if host_arch == 'unknown' +diff --git a/meson_options.txt b/meson_options.txt +index 61996300d5..94a9b479bd 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -374,3 +374,6 @@ option('qemu_ga_version', type: 'string', value: '', + + option('hexagon_idef_parser', type : 'boolean', value : true, + description: 'use idef-parser to automatically generate TCG code for the Hexagon frontend') ++ ++option('mbind_by_proportion', type: 'feature', value: 'auto', ++ description: ' support of one guest numa node alloc memory from multi host nodes') +diff --git a/qapi/qom.json b/qapi/qom.json +index e0590a6019..d1fbe2b0a2 100644 +--- a/qapi/qom.json ++++ b/qapi/qom.json +@@ -624,6 +624,7 @@ + { 'struct': 'MemoryBackendProperties', + 'data': { '*dump': 'bool', + '*host-nodes': ['uint16'], ++ '*host-nodes-propertion': 'str', + '*merge': 'bool', + '*policy': 'HostMemPolicy', + '*prealloc': 'bool', +diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh +index 8604fe8ffa..d5d9130540 100644 +--- a/scripts/meson-buildoptions.sh ++++ b/scripts/meson-buildoptions.sh +@@ -225,6 +225,9 @@ meson_options_help() { + printf "%s\n" ' zstd zstd compression support' + printf "%s\n" ' qpl Query Processing Library support' + printf "%s\n" ' uadk UADK Library support' ++ printf "%s\n" ' mbind-by-proportion' ++ printf "%s\n" ' support of one guest numa node alloc memory from multi' ++ printf "%s\n" ' host nodes' + } + _meson_option_parse() { + case $1 in +@@ -571,6 +574,8 @@ _meson_option_parse() { + --disable-qpl) printf "%s" -Dqpl=disabled ;; + --enable-uadk) printf "%s" -Duadk=enabled ;; + --disable-uadk) printf "%s" -Duadk=disabled ;; ++ --enable-mbind-by-proportion) printf "%s" -Dmbind_by_proportion=enabled ;; ++ --disable-mbind-by-proportion) printf "%s" -Dmbind_by_proportion=disabled ;; + *) return 1 ;; + esac + } +-- +2.33.0 + diff --git a/qemu.spec b/qemu.spec index 7b2654f4..b170a5b2 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 8.2.0 -Release: 51 +Release: 52 Epoch: 11 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -1134,6 +1134,8 @@ Patch1117: hw-arm-virt-Initial-support-to-set-target_impl-CPUs.patch Patch1118: target-arm-kvm-Use-PSCI_VERSIOn-for-version-info.patch Patch1119: target-arm-kvm-Set-DISCOVER_IMPL_-hypercalls.patch Patch1120: Fix-the-compilation-of-target-arm-softmmu.patch +Patch1121: trace-Add-trace-to-measure-hot-migrate-downtime.patch +Patch1122: backends-Add-support-of-one-guest-numa-node-alloc-me.patch BuildRequires: flex BuildRequires: gcc @@ -1866,6 +1868,10 @@ getent passwd qemu >/dev/null || \ /bin/systemctl try-restart systemd-binfmt.service &>/dev/null || : %changelog +* Fri Nov 13 2025 Pengrui Zhang - 11:8.2.0-52 +- trace: Add trace to measure hot migrate downtime +- backends: Add support of one guest numa node alloc memory from multi host nodes + * Wed Nov 5 2025 huangyan - 11:8.2.0-51 - Add qemu-user package for arm, aarch64, riscv32, riscv64 targets - Add user-static, user-binfmt package for statically-linked QEMU user emulator diff --git a/trace-Add-trace-to-measure-hot-migrate-downtime.patch b/trace-Add-trace-to-measure-hot-migrate-downtime.patch new file mode 100644 index 00000000..9e6fec7b --- /dev/null +++ b/trace-Add-trace-to-measure-hot-migrate-downtime.patch @@ -0,0 +1,47 @@ +From e1ddab5665118d3ebb3f8e9f86f3a09900dfbabf Mon Sep 17 00:00:00 2001 +From: Chengfei Huang +Date: Mon, 19 May 2025 18:44:01 +0800 +Subject: [PATCH] trace: Add trace to measure hot migrate downtime + +--- + system/cpus.c | 3 +++ + system/trace-events | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/system/cpus.c b/system/cpus.c +index d9de09b9e8..9af5e22157 100644 +--- a/system/cpus.c ++++ b/system/cpus.c +@@ -281,6 +281,8 @@ static int do_vm_stop(RunState state, bool send_stop) + runstate_set(state); + cpu_disable_ticks(); + pause_all_vcpus(); ++ trace_all_vcpus_paused(); ++ + vm_state_notify(0, state); + if (send_stop) { + qapi_event_send_stop(); +@@ -752,6 +754,7 @@ int vm_prepare_start(bool step_pending) + cpu_enable_ticks(); + runstate_set(RUN_STATE_RUNNING); + vm_state_notify(1, RUN_STATE_RUNNING); ++ trace_all_vcpus_prepared(); + return 0; + } + +diff --git a/system/trace-events b/system/trace-events +index 69c9044151..ba0966497b 100644 +--- a/system/trace-events ++++ b/system/trace-events +@@ -23,6 +23,8 @@ global_dirty_changed(unsigned int bitmask) "bitmask 0x%"PRIx32 + + # cpus.c + vm_stop_flush_all(int ret) "ret %d" ++all_vcpus_paused(void) "" ++all_vcpus_prepared(void) "" + + # vl.c + vm_state_notify(int running, int reason, const char *reason_str) "running %d reason %d (%s)" +-- +2.33.0 + -- Gitee