diff --git a/0342-hw-vfio-iommufd-Control-dirty-tracking-for-nesting-p.patch b/0342-hw-vfio-iommufd-Control-dirty-tracking-for-nesting-p.patch new file mode 100644 index 0000000..318e76e --- /dev/null +++ b/0342-hw-vfio-iommufd-Control-dirty-tracking-for-nesting-p.patch @@ -0,0 +1,124 @@ +From 17d16bc8cbf2849fa885280b49381fd2c1d039ca Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 1 Apr 2026 09:41:33 +0100 +Subject: [PATCH] hw/vfio/iommufd: Control dirty tracking for nesting parent + HWPT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +QEMU smmuv3 accel does not support live migration yet, so dirty +tracking for the nesting parent HWPT is not useful. + +Also, nested vIOMMU use cases can break on some platforms. For +example, SMMUv3 with HTTU may advertise dirty tracking capability, +but the kernel supports it only for stage-1. Requesting dirty +tracking for a nesting parent HWPT (stage-2) can fail. + +Add a vIOMMU flag to explicitly request dirty tracking for the +nesting parent HWPT. For nested cases, dirty tracking is enabled +only when requested by the vIOMMU. + +Non-nested cases and Intel vIOMMU keep the existing behavior. + +Conflicts: + - hw/i386/intel_iommu.c: function "vtd_get_viommu_flags" +missing on this context. Since this commit is targeting +only aarch64, removing all changes to intel_iommu. + +Fixes: fc6dafb98cec ("hw/arm/smmuv3: Implement get_viommu_cap() callback") +Signed-off-by: Shameer Kolothum +Reviewed-by: Zhenzhong Duan +Link: https://lore.kernel.org/qemu-devel/20260401084133.56266-1-skolothumtho@nvidia.com +Signed-off-by: Cédric Le Goater +--- + hw/vfio/device.c | 11 +++++++++++ + hw/vfio/iommufd.c | 11 +++++++++-- + include/hw/core/iommu.h | 2 ++ + include/hw/vfio/vfio-device.h | 1 + + 4 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/hw/vfio/device.c b/hw/vfio/device.c +index 7bdb6db923..9c38bb89dc 100644 +--- a/hw/vfio/device.c ++++ b/hw/vfio/device.c +@@ -525,6 +525,17 @@ int vfio_device_get_feature(VFIODevice *vbasedev, + return vbasedev->io_ops->device_feature(vbasedev, feature); + } + ++bool vfio_device_get_viommu_flags_want_nesting_dirty(VFIODevice *vbasedev) ++{ ++ VFIOPCIDevice *vdev = vfio_pci_from_vfio_device(vbasedev); ++ ++ if (vdev) { ++ return !!(pci_device_get_viommu_flags(PCI_DEVICE(vdev)) & ++ VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING); ++ } ++ return false; ++} ++ + bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev) + { + VFIOPCIDevice *vdev = vfio_pci_from_vfio_device(vbasedev); +diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c +index dc9100e772..a7589e685c 100644 +--- a/hw/vfio/iommufd.c ++++ b/hw/vfio/iommufd.c +@@ -307,6 +307,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev, + IOMMUFDBackend *iommufd = vbasedev->iommufd; + VFIOContainer *bcontainer = VFIO_IOMMU(container); + uint32_t type = IOMMU_HW_INFO_TYPE_DEFAULT, flags = 0; ++ bool viommu_nesting, viommu_nesting_dirty; + uint64_t hw_caps; + VendorCaps caps; + VFIOIOASHwpt *hwpt; +@@ -359,8 +360,14 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev, + return false; + } + ++ viommu_nesting = vfio_device_get_viommu_flags_want_nesting(vbasedev); ++ viommu_nesting_dirty = ++ vfio_device_get_viommu_flags_want_nesting_dirty(vbasedev); ++ + if (hw_caps & IOMMU_HW_CAP_DIRTY_TRACKING) { +- flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING; ++ if (!viommu_nesting || viommu_nesting_dirty) { ++ flags |= IOMMU_HWPT_ALLOC_DIRTY_TRACKING; ++ } + } + + /* +@@ -368,7 +375,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev, + * force to create it so that it could be reused by vIOMMU to create + * nested HWPT. + */ +- if (vfio_device_get_viommu_flags_want_nesting(vbasedev)) { ++ if (viommu_nesting) { + flags |= IOMMU_HWPT_ALLOC_NEST_PARENT; + } + +diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h +index 86af315c15..cd59a367ce 100644 +--- a/include/hw/core/iommu.h ++++ b/include/hw/core/iommu.h +@@ -21,6 +21,8 @@ enum viommu_flags { + /* vIOMMU needs nesting parent HWPT to create nested HWPT */ + VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0), + VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1), ++ /* vIOMMU needs dirty tracking on the nesting parent HWPT for nested use */ ++ VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING = BIT_ULL(2), + }; + + /* Host IOMMU quirks. Extracted from host IOMMU capabilities */ +diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h +index 27e2976593..24eb840b16 100644 +--- a/include/hw/vfio/vfio-device.h ++++ b/include/hw/vfio/vfio-device.h +@@ -261,6 +261,7 @@ void vfio_device_unprepare(VFIODevice *vbasedev); + int vfio_device_get_feature(VFIODevice *vbasedev, + struct vfio_device_feature *feature); + bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev); ++bool vfio_device_get_viommu_flags_want_nesting_dirty(VFIODevice *vbasedev); + + int vfio_device_get_region_info(VFIODevice *vbasedev, int index, + struct vfio_region_info **info); diff --git a/0343-vmstate-Introduce-VMSTATE_VARRAY_INT32_ALLOC.patch b/0343-vmstate-Introduce-VMSTATE_VARRAY_INT32_ALLOC.patch new file mode 100644 index 0000000..6c3e6a8 --- /dev/null +++ b/0343-vmstate-Introduce-VMSTATE_VARRAY_INT32_ALLOC.patch @@ -0,0 +1,58 @@ +From 4b5ca7e702db3573a5392c96b43bdb01c8e2866d Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] vmstate: Introduce VMSTATE_VARRAY_INT32_ALLOC + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [1/16] 54c0c7a95e98c7d6eb73119763121c3ba30e8c58 (eauger1/centos-qemu-kvm) + +Already existing VMSTATE_VARRAY_INT32 requires an array to be +pre-allocated, however there are cases when the size is not known in +advance and there is no real need to enforce it. + +Introduce VMSTATE_VARRAY_INT32_ALLOC as we currently have for UINT32 +and UINT16. + +The first user of this variant will be the target/arm/machine.c cpreg +indexes/values arrays. + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Reviewed-by: Peter Xu +Message-id: 20260304101625.1962633-2-eric.auger@redhat.com +Suggested-by: Peter Maydell +Reviewed-by: Peter Maydell +Reviewed-by: Peter Xu +Signed-off-by: Peter Maydell +(cherry picked from commit f555338df754b37e042d5b88610c34b1d1845383) +Signed-off-by: Eric Auger +--- + include/migration/vmstate.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h +index 5fe9bbf390..47a1dc1810 100644 +--- a/include/migration/vmstate.h ++++ b/include/migration/vmstate.h +@@ -432,6 +432,16 @@ extern const VMStateInfo vmstate_info_qlist; + .offset = vmstate_offset_pointer(_state, _field, _type), \ + } + ++#define VMSTATE_VARRAY_INT32_ALLOC(_field, _state, _field_num, _version, _info, _type) {\ ++ .name = (stringify(_field)), \ ++ .version_id = (_version), \ ++ .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \ ++ .info = &(_info), \ ++ .size = sizeof(_type), \ ++ .flags = VMS_VARRAY_INT32 | VMS_POINTER | VMS_ALLOC, \ ++ .offset = vmstate_offset_pointer(_state, _field, _type), \ ++} ++ + #define VMSTATE_VARRAY_UINT32_ALLOC(_field, _state, _field_num, _version, _info, _type) {\ + .name = (stringify(_field)), \ + .version_id = (_version), \ diff --git a/0344-target-arm-Move-compare_u64-to-helper.c.patch b/0344-target-arm-Move-compare_u64-to-helper.c.patch new file mode 100644 index 0000000..2e617c7 --- /dev/null +++ b/0344-target-arm-Move-compare_u64-to-helper.c.patch @@ -0,0 +1,87 @@ +From 51067e840f35f0f3ac4e4f69f5ec1091d5e7e5ba Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 11 May 2026 12:06:24 -0400 +Subject: [PATCH] target/arm: Move compare_u64 to helper.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [2/16] 497fedf076c0f7945bbe584efc060d7238c50837 (eauger1/centos-qemu-kvm) + +We will use this function beyond kvm.c. + +Reviewed-by: Manos Pitsidianakis +Signed-off-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +(cherry picked from commit 5a8af95cb31122d2fcd2e6d3427b8e8427cd8bdc) +Signed-off-by: Eric Auger +--- + target/arm/helper.c | 11 +++++++++++ + target/arm/internals.h | 3 +++ + target/arm/kvm.c | 11 ----------- + 3 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 0c1299ff84..d230f9e766 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -40,6 +40,17 @@ + + static void switch_mode(CPUARMState *env, int mode); + ++int compare_u64(const void *a, const void *b) ++{ ++ if (*(uint64_t *)a > *(uint64_t *)b) { ++ return 1; ++ } ++ if (*(uint64_t *)a < *(uint64_t *)b) { ++ return -1; ++ } ++ return 0; ++} ++ + uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + assert(ri->fieldoffset); +diff --git a/target/arm/internals.h b/target/arm/internals.h +index 1b3d0244fd..08e2acdb99 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -1981,4 +1981,7 @@ void vfp_clear_float_status_exc_flags(CPUARMState *env); + void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask); + bool arm_pan_enabled(CPUARMState *env); + ++/* Compare uint64_t for qsort and bsearch. */ ++int compare_u64(const void *a, const void *b); ++ + #endif +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 864f75600f..366a096287 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -718,17 +718,6 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, + memory_region_ref(kd->mr); + } + +-static int compare_u64(const void *a, const void *b) +-{ +- if (*(uint64_t *)a > *(uint64_t *)b) { +- return 1; +- } +- if (*(uint64_t *)a < *(uint64_t *)b) { +- return -1; +- } +- return 0; +-} +- + /* + * cpreg_values are sorted in ascending order by KVM register ID + * (see kvm_arm_init_cpreg_list). This allows us to cheaply find diff --git a/0345-target-arm-Convert-init_cpreg_list-to-g_hash_table_f.patch b/0345-target-arm-Convert-init_cpreg_list-to-g_hash_table_f.patch new file mode 100644 index 0000000..9949b08 --- /dev/null +++ b/0345-target-arm-Convert-init_cpreg_list-to-g_hash_table_f.patch @@ -0,0 +1,134 @@ +From a89686bb07272e8c705cb2aefac561c9a26d9998 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 11 May 2026 12:06:39 -0400 +Subject: [PATCH] target/arm: Convert init_cpreg_list to g_hash_table_foreach +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [3/16] 704e757f243d944ee544496d50b7ead4a1e2e681 (eauger1/centos-qemu-kvm) + +Adjust count_cpreg and add_cpreg_to_list to be used with +g_hash_table_foreach instead of g_list_foreach. In this way we have +the ARMCPRegInfo pointer directly rather than having to look it up +from the key. + +Delay the sorting of the cpreg_indexes until after add_cpreg_to_list. +This allows us to sort the data that we actually care about, +the kvm id, as computed within add_cpreg_to_list, instead of +having to repeatedly compute the kvm id within cpreg_key_compare. + +Signed-off-by: Richard Henderson +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +(cherry picked from commit dee3c0c2cf9848cd849744474cdac108ce68a1ef) +Signed-off-by: Eric Auger +--- + target/arm/helper.c | 54 ++++++++++++++++++--------------------------- + 1 file changed, 21 insertions(+), 33 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index d230f9e766..1cff4c5a68 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -209,11 +209,11 @@ bool write_list_to_cpustate(ARMCPU *cpu) + return ok; + } + +-static void add_cpreg_to_list(gpointer key, gpointer opaque) ++static void add_cpreg_to_list(gpointer key, gpointer value, gpointer opaque) + { + ARMCPU *cpu = opaque; + uint32_t regidx = (uintptr_t)key; +- const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx); ++ const ARMCPRegInfo *ri = value; + + if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) { + cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx); +@@ -222,61 +222,49 @@ static void add_cpreg_to_list(gpointer key, gpointer opaque) + } + } + +-static void count_cpreg(gpointer key, gpointer opaque) ++static void count_cpreg(gpointer key, gpointer value, gpointer opaque) + { + ARMCPU *cpu = opaque; +- const ARMCPRegInfo *ri; +- +- ri = g_hash_table_lookup(cpu->cp_regs, key); ++ const ARMCPRegInfo *ri = value; + + if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) { + cpu->cpreg_array_len++; + } + } + +-static gint cpreg_key_compare(gconstpointer a, gconstpointer b, gpointer d) +-{ +- uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a); +- uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b); +- +- if (aidx > bidx) { +- return 1; +- } +- if (aidx < bidx) { +- return -1; +- } +- return 0; +-} +- + void init_cpreg_list(ARMCPU *cpu) + { + /* + * Initialise the cpreg_tuples[] array based on the cp_regs hash. + * Note that we require cpreg_tuples[] to be sorted by key ID. + */ +- GList *keys; + int arraylen; + +- keys = g_hash_table_get_keys(cpu->cp_regs); +- keys = g_list_sort_with_data(keys, cpreg_key_compare, NULL); +- + cpu->cpreg_array_len = 0; +- +- g_list_foreach(keys, count_cpreg, cpu); ++ g_hash_table_foreach(cpu->cp_regs, count_cpreg, cpu); + + arraylen = cpu->cpreg_array_len; +- cpu->cpreg_indexes = g_new(uint64_t, arraylen); +- cpu->cpreg_values = g_new(uint64_t, arraylen); +- cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen); +- cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen); +- cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len; ++ if (arraylen) { ++ cpu->cpreg_indexes = g_new(uint64_t, arraylen); ++ cpu->cpreg_values = g_new(uint64_t, arraylen); ++ cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen); ++ cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen); ++ } else { ++ cpu->cpreg_indexes = NULL; ++ cpu->cpreg_values = NULL; ++ cpu->cpreg_vmstate_indexes = NULL; ++ cpu->cpreg_vmstate_values = NULL; ++ } ++ cpu->cpreg_vmstate_array_len = arraylen; + cpu->cpreg_array_len = 0; + +- g_list_foreach(keys, add_cpreg_to_list, cpu); ++ g_hash_table_foreach(cpu->cp_regs, add_cpreg_to_list, cpu); + + assert(cpu->cpreg_array_len == arraylen); + +- g_list_free(keys); ++ if (arraylen) { ++ qsort(cpu->cpreg_indexes, arraylen, sizeof(uint64_t), compare_u64); ++ } + } + + bool arm_pan_enabled(CPUARMState *env) diff --git a/0346-target-arm-machine-Use-VMSTATE_VARRAY_INT32_ALLOC-fo.patch b/0346-target-arm-machine-Use-VMSTATE_VARRAY_INT32_ALLOC-fo.patch new file mode 100644 index 0000000..a945011 --- /dev/null +++ b/0346-target-arm-machine-Use-VMSTATE_VARRAY_INT32_ALLOC-fo.patch @@ -0,0 +1,191 @@ +From d11effe48c156e7e389bfc23a0ca33b93e944241 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] target/arm/machine: Use VMSTATE_VARRAY_INT32_ALLOC for cpreg + arrays + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [4/16] 833ad7f2be8a02eb811c8562d809e4cc2eedc2a6 (eauger1/centos-qemu-kvm) + +Conflicts: +- contextual conflict in target/arm/trace-events as we don't have + cpu.c, arm-powerctl.c, tcg/psci.c and hvf/hvf.c trace events +- target/arm/whpx/whpx-all.c does not exist downstream + +This removes the need for explicitly allocating cpreg_vmstate arrays. +On post save we simply point to cpreg arrays and set the length +accordingly. + +Remove VMSTATE_VARRAY_INT32 for cpreg_vmstate_array_len as now +the array is dynamically allocated. + +Also add a trace point on post_load to trace potential mismatch +between the number of incoming cpregs versus current ones. + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260304101625.1962633-3-eric.auger@redhat.com +Suggested-by: Peter Maydell +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit ab2ddc7b662d34c242ddfcfbe35996417b047ce2) +Signed-off-by: Eric Auger +--- + target/arm/helper.c | 5 ----- + target/arm/kvm.c | 5 ----- + target/arm/machine.c | 45 +++++++++++++++++++++++++++++------------ + target/arm/trace-events | 3 +++ + 4 files changed, 35 insertions(+), 23 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 1cff4c5a68..5e643ed6b2 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -247,15 +247,10 @@ void init_cpreg_list(ARMCPU *cpu) + if (arraylen) { + cpu->cpreg_indexes = g_new(uint64_t, arraylen); + cpu->cpreg_values = g_new(uint64_t, arraylen); +- cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen); +- cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen); + } else { + cpu->cpreg_indexes = NULL; + cpu->cpreg_values = NULL; +- cpu->cpreg_vmstate_indexes = NULL; +- cpu->cpreg_vmstate_values = NULL; + } +- cpu->cpreg_vmstate_array_len = arraylen; + cpu->cpreg_array_len = 0; + + g_hash_table_foreach(cpu->cp_regs, add_cpreg_to_list, cpu); +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 366a096287..f1be509c86 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -805,12 +805,7 @@ static int kvm_arm_init_cpreg_list(ARMCPU *cpu) + + cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen); + cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen); +- cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes, +- arraylen); +- cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values, +- arraylen); + cpu->cpreg_array_len = arraylen; +- cpu->cpreg_vmstate_array_len = arraylen; + + for (i = 0, arraylen = 0; i < rlp->n; i++) { + uint64_t regidx = rlp->reg[i]; +diff --git a/target/arm/machine.c b/target/arm/machine.c +index 6986915bee..5caf2885c2 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -1,5 +1,6 @@ + #include "qemu/osdep.h" + #include "cpu.h" ++#include "trace.h" + #include "qemu/error-report.h" + #include "system/kvm.h" + #include "system/tcg.h" +@@ -894,11 +895,14 @@ static int cpu_pre_save(void *opaque) + } + } + ++ /* ++ * On outbound migration, send the data in our cpreg_{values,indexes} ++ * arrays. The migration code will not allocate anything, but just ++ * reads the data pointed to by the VMSTATE_VARRAY_INT32_ALLOC() fields. ++ */ ++ cpu->cpreg_vmstate_indexes = cpu->cpreg_indexes; ++ cpu->cpreg_vmstate_values = cpu->cpreg_values; + cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len; +- memcpy(cpu->cpreg_vmstate_indexes, cpu->cpreg_indexes, +- cpu->cpreg_array_len * sizeof(uint64_t)); +- memcpy(cpu->cpreg_vmstate_values, cpu->cpreg_values, +- cpu->cpreg_array_len * sizeof(uint64_t)); + + return 0; + } +@@ -911,6 +915,9 @@ static int cpu_post_save(void *opaque) + pmu_op_finish(&cpu->env); + } + ++ cpu->cpreg_vmstate_indexes = NULL; ++ cpu->cpreg_vmstate_values = NULL; ++ + return 0; + } + +@@ -944,6 +951,9 @@ static int cpu_pre_load(void *opaque) + pmu_op_start(env); + } + ++ g_assert(!cpu->cpreg_vmstate_indexes); ++ g_assert(!cpu->cpreg_vmstate_values); ++ + return 0; + } + +@@ -953,6 +963,9 @@ static int cpu_post_load(void *opaque, int version_id) + CPUARMState *env = &cpu->env; + int i, v; + ++ trace_cpu_post_load(cpu->cpreg_vmstate_array_len, ++ cpu->cpreg_array_len); ++ + /* + * Handle migration compatibility from old QEMU which didn't + * send the irq-line-state subsection. A QEMU without it did not +@@ -1004,6 +1017,11 @@ static int cpu_post_load(void *opaque, int version_id) + } + } + ++ g_free(cpu->cpreg_vmstate_indexes); ++ g_free(cpu->cpreg_vmstate_values); ++ cpu->cpreg_vmstate_indexes = NULL; ++ cpu->cpreg_vmstate_values = NULL; ++ + /* + * Misaligned thumb pc is architecturally impossible. Fail the + * incoming migration. For TCG it would trigger the assert in +@@ -1071,16 +1089,17 @@ const VMStateDescription vmstate_arm_cpu = { + VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5), + VMSTATE_UINT64_ARRAY(env.elr_el, ARMCPU, 4), + VMSTATE_UINT64_ARRAY(env.sp_el, ARMCPU, 4), +- /* The length-check must come before the arrays to avoid +- * incoming data possibly overflowing the array. ++ /* ++ * The length must come before the arrays so we can ++ * allocate the arrays before their data arrives + */ +- VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU), +- VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU, +- cpreg_vmstate_array_len, +- 0, vmstate_info_uint64, uint64_t), +- VMSTATE_VARRAY_INT32(cpreg_vmstate_values, ARMCPU, +- cpreg_vmstate_array_len, +- 0, vmstate_info_uint64, uint64_t), ++ VMSTATE_INT32(cpreg_vmstate_array_len, ARMCPU), ++ VMSTATE_VARRAY_INT32_ALLOC(cpreg_vmstate_indexes, ARMCPU, ++ cpreg_vmstate_array_len, ++ 0, vmstate_info_uint64, uint64_t), ++ VMSTATE_VARRAY_INT32_ALLOC(cpreg_vmstate_values, ARMCPU, ++ cpreg_vmstate_array_len, ++ 0, vmstate_info_uint64, uint64_t), + VMSTATE_UINT64(env.exclusive_addr, ARMCPU), + VMSTATE_UINT64(env.exclusive_val, ARMCPU), + VMSTATE_UINT64(env.exclusive_high, ARMCPU), +diff --git a/target/arm/trace-events b/target/arm/trace-events +index 4438dce7be..4e2502af9f 100644 +--- a/target/arm/trace-events ++++ b/target/arm/trace-events +@@ -13,3 +13,6 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d" + + # kvm.c + kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 ++ ++# machine.c ++cpu_post_load(uint32_t cpreg_vmstate_array_len, uint32_t cpreg_array_len) "cpreg_vmstate_array_len=%d cpreg_array_len=%d" diff --git a/0347-target-arm-kvm-Export-kvm_print_register_name.patch b/0347-target-arm-kvm-Export-kvm_print_register_name.patch new file mode 100644 index 0000000..9688a69 --- /dev/null +++ b/0347-target-arm-kvm-Export-kvm_print_register_name.patch @@ -0,0 +1,77 @@ +From b70cf627c0a32a57c8e529ba1262001ae036d26b Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] target/arm/kvm: Export kvm_print_register_name() + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [5/16] 66bc6985b3162adca02cac4efbbb86f5e973ed7f (eauger1/centos-qemu-kvm) + +Conflicts: contextual conflicts in target/arm/kvm-stub.c +and target/arm/kvm_arm.h since we don't have arm_gic_cap_kvm_probe() +downstream + +We want to use kvm_print_register_name() in machine.c so +let's export the helper and implement a stub when kvm +is not enabled. + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260304101625.1962633-4-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit 5ae081fb493510f62280afc005aa36f702192539) +Signed-off-by: Eric Auger +--- + target/arm/kvm-stub.c | 5 +++++ + target/arm/kvm.c | 2 +- + target/arm/kvm_arm.h | 9 +++++++++ + 3 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c +index c93462c5b9..58b37e0dfe 100644 +--- a/target/arm/kvm-stub.c ++++ b/target/arm/kvm-stub.c +@@ -124,3 +124,8 @@ bool kvm_arm_cpu_post_load(ARMCPU *cpu) + { + g_assert_not_reached(); + } ++ ++char *kvm_print_register_name(uint64_t regidx) ++{ ++ g_assert_not_reached(); ++} +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index f1be509c86..ef29256dfe 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -911,7 +911,7 @@ static gchar *kvm_print_sve_register_name(uint64_t regidx) + } + } + +-static gchar *kvm_print_register_name(uint64_t regidx) ++char *kvm_print_register_name(uint64_t regidx) + { + switch ((regidx & KVM_REG_ARM_COPROC_MASK)) { + case KVM_REG_ARM_CORE: +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 6a9b6374a6..c4e7dc28ef 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -263,4 +263,13 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp); + + void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level); + ++/* ++ * kvm_print_register_name: ++ * @regidx: register KVM index ++ * ++ * Returns a human-readable string representing this register ++ * The caller must free the string with g_free(). ++ */ ++char *kvm_print_register_name(uint64_t regidx); ++ + #endif diff --git a/0348-target-arm-kvm-Tweak-print_register_name-for-arm64-s.patch b/0348-target-arm-kvm-Tweak-print_register_name-for-arm64-s.patch new file mode 100644 index 0000000..06f183d --- /dev/null +++ b/0348-target-arm-kvm-Tweak-print_register_name-for-arm64-s.patch @@ -0,0 +1,41 @@ +From 14931aaec9f141f7ee601020991a6ddc5d4a2c70 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] target/arm/kvm: Tweak print_register_name() for arm64 system + register + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [6/16] e434272a6ecab513d6bc8c4811cd8e1463cdbfad (eauger1/centos-qemu-kvm) + +As opposed to other register types, arm64 system register decoding +is not introduced by any 'register' mention which can lead to +unfriendly user-facing traces. Let's add "system register" + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260304101625.1962633-5-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit 3e0a3a8e91efabef01dad8ea1cd1f13dcc46b14d) +Signed-off-by: Eric Auger +--- + target/arm/kvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index ef29256dfe..fe731cc49f 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -919,7 +919,7 @@ char *kvm_print_register_name(uint64_t regidx) + case KVM_REG_ARM_DEMUX: + return g_strdup_printf("demuxed reg %"PRIx64, regidx); + case KVM_REG_ARM64_SYSREG: +- return g_strdup_printf("op0:%d op1:%d crn:%d crm:%d op2:%d", ++ return g_strdup_printf("system register op0:%d op1:%d crn:%d crm:%d op2:%d", + CP_REG_ARM64_SYSREG_OP(regidx, OP0), + CP_REG_ARM64_SYSREG_OP(regidx, OP1), + CP_REG_ARM64_SYSREG_OP(regidx, CRN), diff --git a/0349-target-arm-machine-Trace-cpreg-names-which-do-not-ma.patch b/0349-target-arm-machine-Trace-cpreg-names-which-do-not-ma.patch new file mode 100644 index 0000000..15a6103 --- /dev/null +++ b/0349-target-arm-machine-Trace-cpreg-names-which-do-not-ma.patch @@ -0,0 +1,90 @@ +From ec93904014f8fd0d461a05c4f18886dfc4d5d21b Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] target/arm/machine: Trace cpreg names which do not match on + migration + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [7/16] 4fd2c91158511a672da05643c961fe55f964fe31 (eauger1/centos-qemu-kvm) + +Whenever there is a mismatch between cpreg indexes in the incoming +stream and cpregs exposed by the destination output the name of +the register. We use a print_register_name() wrapper helper. At the +moment we are only able to do a nice decoding of the index for +KVM regs. + +Without this patch, the error would be: +qemu-system-aarch64: load of migration failed: Operation not permitted: +error while loading state for instance 0x0 of device 'cpu': post load +hook failed for: cpu, version_id: 22, minimum_version: 22, ret: -1 +which is not helpful for the end user to understand the actual +issue. + +This patch adds the actual information about the probme: +qemu-system-aarch64: cpu_post_load: system register +op0:3 op1:0 crn:2 crm:0 op2:3 in the incoming stream but +unknown on the destination, fail migration + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260304101625.1962633-6-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit eac1e610f48923084cb07b3f1eaa05f5fedccd85) +Signed-off-by: Eric Auger +--- + target/arm/machine.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/target/arm/machine.c b/target/arm/machine.c +index 5caf2885c2..36c9d9946e 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -1,5 +1,6 @@ + #include "qemu/osdep.h" + #include "cpu.h" ++#include "cpregs.h" + #include "trace.h" + #include "qemu/error-report.h" + #include "system/kvm.h" +@@ -957,6 +958,15 @@ static int cpu_pre_load(void *opaque) + return 0; + } + ++static gchar *print_register_name(uint64_t kvm_regidx) ++{ ++ if (kvm_enabled()) { ++ return kvm_print_register_name(kvm_regidx); ++ } else { ++ return g_strdup_printf("system register 0x%x", kvm_to_cpreg_id(kvm_regidx)); ++ } ++} ++ + static int cpu_post_load(void *opaque, int version_id) + { + ARMCPU *cpu = opaque; +@@ -995,11 +1005,18 @@ static int cpu_post_load(void *opaque, int version_id) + for (i = 0, v = 0; i < cpu->cpreg_array_len + && v < cpu->cpreg_vmstate_array_len; i++) { + if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) { +- /* register in our list but not incoming : skip it */ ++ g_autofree gchar *name = print_register_name(cpu->cpreg_indexes[i]); ++ ++ warn_report("%s: %s " ++ "expected by the destination but not in the incoming stream: " ++ "skip it", __func__, name); + continue; + } + if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) { +- /* register in their list but not ours: fail migration */ ++ g_autofree gchar *name = print_register_name(cpu->cpreg_vmstate_indexes[v]); ++ ++ error_report("%s: %s in the incoming stream but unknown on the destination: " ++ "fail migration", __func__, name); + return -1; + } + /* matching register, copy the value over */ diff --git a/0350-target-arm-machine-Trace-all-register-mismatches.patch b/0350-target-arm-machine-Trace-all-register-mismatches.patch new file mode 100644 index 0000000..198f834 --- /dev/null +++ b/0350-target-arm-machine-Trace-all-register-mismatches.patch @@ -0,0 +1,75 @@ +From b1878dbb2058e2c5f61a01a0bbc91f83fc014267 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] target/arm/machine: Trace all register mismatches + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [8/16] 270563b74465e4bf42901a2f0332a61621b22123 (eauger1/centos-qemu-kvm) + +At the moment, cpu_post_load() exits with error on the first +catch of unexpected register in the incoming stream. Let the code +go further and trace all the issues before exiting. + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260304101625.1962633-7-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit e25c63c3b368118dc109e49393554f85f1203d1e) +Signed-off-by: Eric Auger +--- + target/arm/machine.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/target/arm/machine.c b/target/arm/machine.c +index 36c9d9946e..70157e000b 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -971,6 +971,7 @@ static int cpu_post_load(void *opaque, int version_id) + { + ARMCPU *cpu = opaque; + CPUARMState *env = &cpu->env; ++ bool fail = false; + int i, v; + + trace_cpu_post_load(cpu->cpreg_vmstate_array_len, +@@ -1003,13 +1004,14 @@ static int cpu_post_load(void *opaque, int version_id) + */ + + for (i = 0, v = 0; i < cpu->cpreg_array_len +- && v < cpu->cpreg_vmstate_array_len; i++) { ++ && v < cpu->cpreg_vmstate_array_len;) { + if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) { + g_autofree gchar *name = print_register_name(cpu->cpreg_indexes[i]); + + warn_report("%s: %s " + "expected by the destination but not in the incoming stream: " + "skip it", __func__, name); ++ i++; + continue; + } + if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) { +@@ -1017,12 +1019,18 @@ static int cpu_post_load(void *opaque, int version_id) + + error_report("%s: %s in the incoming stream but unknown on the destination: " + "fail migration", __func__, name); +- return -1; ++ v++; ++ fail = true; ++ continue; + } + /* matching register, copy the value over */ + cpu->cpreg_values[i] = cpu->cpreg_vmstate_values[v]; ++ i++; + v++; + } ++ if (fail) { ++ return -1; ++ } + + if (kvm_enabled()) { + if (!kvm_arm_cpu_post_load(cpu)) { diff --git a/0351-target-arm-machine-Fix-detection-of-unknown-incoming.patch b/0351-target-arm-machine-Fix-detection-of-unknown-incoming.patch new file mode 100644 index 0000000..98b8690 --- /dev/null +++ b/0351-target-arm-machine-Fix-detection-of-unknown-incoming.patch @@ -0,0 +1,122 @@ +From 80a3a9a35e8498ecb4cb0ba04dc5c9dee7a1e666 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Fri, 6 Mar 2026 09:01:12 +0000 +Subject: [PATCH] target/arm/machine: Fix detection of unknown incoming cpregs + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [9/16] 6450081257ce770c0825a69e794036bc181b5a6c (eauger1/centos-qemu-kvm) + +Currently the check of cpreg index matches fail to detect +a situation where the length of both arrays is same but +- destination has an extra register not found in the incoming stream (idx1) +- source has an extra register not found in the destination (idx2) + where idx1 < = idx2 +Normally this should fail but it does not. + +Fix the logic to scan all indexes. + +Fixes: 721fae12536 ("target-arm: Convert TCG to using (index,value) list for cp migration") +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260304101625.1962633-8-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit dbfed8d80837ff7d36e763163f38549169ee64cc) +Signed-off-by: Eric Auger +--- + target/arm/machine.c | 61 +++++++++++++++++++++++++++++++++++--------- + 1 file changed, 49 insertions(+), 12 deletions(-) + +diff --git a/target/arm/machine.c b/target/arm/machine.c +index 70157e000b..e0447083ee 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -967,6 +967,35 @@ static gchar *print_register_name(uint64_t kvm_regidx) + } + } + ++/* ++ * Handle the situation where @kvmidx is on destination but not ++ * in the incoming stream. This never fails the migration. ++ */ ++static void handle_cpreg_missing_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) ++{ ++ g_autofree gchar *name = print_register_name(kvmidx); ++ ++ warn_report("%s: %s " ++ "expected by the destination but not in the incoming stream: " ++ "skip it", __func__, name); ++} ++ ++/* ++ * Handle the situation where @kvmidx is in the incoming stream ++ * but not on destination. This currently fails the migration but ++ * we plan to accomodate some exceptions, hence the boolean returned value. ++ */ ++static bool handle_cpreg_only_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) ++{ ++ g_autofree gchar *name = print_register_name(kvmidx); ++ bool fail = true; ++ ++ error_report("%s: %s in the incoming stream but unknown on the " ++ "destination: fail migration", __func__, name); ++ ++ return fail; ++} ++ + static int cpu_post_load(void *opaque, int version_id) + { + ARMCPU *cpu = opaque; +@@ -1006,21 +1035,12 @@ static int cpu_post_load(void *opaque, int version_id) + for (i = 0, v = 0; i < cpu->cpreg_array_len + && v < cpu->cpreg_vmstate_array_len;) { + if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) { +- g_autofree gchar *name = print_register_name(cpu->cpreg_indexes[i]); +- +- warn_report("%s: %s " +- "expected by the destination but not in the incoming stream: " +- "skip it", __func__, name); +- i++; ++ handle_cpreg_missing_in_incoming_stream(cpu, cpu->cpreg_indexes[i++]); + continue; + } + if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) { +- g_autofree gchar *name = print_register_name(cpu->cpreg_vmstate_indexes[v]); +- +- error_report("%s: %s in the incoming stream but unknown on the destination: " +- "fail migration", __func__, name); +- v++; +- fail = true; ++ fail = handle_cpreg_only_in_incoming_stream(cpu, ++ cpu->cpreg_vmstate_indexes[v++]); + continue; + } + /* matching register, copy the value over */ +@@ -1028,6 +1048,23 @@ static int cpu_post_load(void *opaque, int version_id) + i++; + v++; + } ++ ++ /* ++ * if we have reached the end of the incoming array but there are ++ * still regs in cpreg, continue parsing the regs which are missing ++ * in the input stream ++ */ ++ for ( ; i < cpu->cpreg_array_len; i++) { ++ handle_cpreg_missing_in_incoming_stream(cpu, cpu->cpreg_indexes[i]); ++ } ++ /* ++ * if we have reached the end of the cpreg array but there are ++ * still regs in the input stream, continue parsing the vmstate array ++ */ ++ for ( ; v < cpu->cpreg_vmstate_array_len; v++) { ++ fail = handle_cpreg_only_in_incoming_stream(cpu, ++ cpu->cpreg_vmstate_indexes[v]); ++ } + if (fail) { + return -1; + } diff --git a/0352-target-arm-cpu-Introduce-the-infrastructure-for-cpre.patch b/0352-target-arm-cpu-Introduce-the-infrastructure-for-cpre.patch new file mode 100644 index 0000000..31289a8 --- /dev/null +++ b/0352-target-arm-cpu-Introduce-the-infrastructure-for-cpre.patch @@ -0,0 +1,241 @@ +From 45314e6772f7b28997596c6585e40ff7e94367f6 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:51 +0200 +Subject: [PATCH] target/arm/cpu: Introduce the infrastructure for cpreg + migration tolerances + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [10/16] 71bbf8b6df2c02de6349343040f7edb827161f4c (eauger1/centos-qemu-kvm) + +Conflicts: contextual conflict in target/arm/internals.h as we don't +have #define MECID_WIDTH 16 introduced by commit +700f08d5829f ("target/arm: Implement FEAT_MEC registers") + +We introduce a datatype for a tolerance with respect to a given +cpreg migration issue. The tolerance applies to a given cpreg kvm index, +and can be of different types: +a) mismatch in cpreg indexes +- ToleranceNotOnBothEnds (cpreg index is allowed to be only present + on one end) +- ToleranceOnlySrcTestValue (cpreg index is allowed to be only + present in source if its value @mask field matches @value) +b) mismatch in cpreg values +- ToleranceDiffInMask (value differences are allowed only within a mask) +- ToleranceFieldLT (incoming field value must be less than a given value) +- ToleranceFieldGT (incoming field value must be greater than a given value) + +A QLIST of such tolerances can be populated using a new helper: +arm_register_cpreg_mig_tolerance() and arm_cpu_match_cpreg_mig_tolerance() +allows to check whether a tolerance exists for a given kvm index and its +criterion is matched. + +callers for those helpers will be introduced in subsequent patches. + +Only registration of migration tolerances related to cpreg index +mismatch is currently allowed. + +Signed-off-by: Eric Auger +Message-id: 20260420140552.104369-2-eric.auger@redhat.com +Signed-off-by: Peter Maydell +Reviewed-by: Peter Maydell +(cherry picked from commit bb36be6fd799c4fdb2ac893cfab7f307c12527f2) +Signed-off-by: Eric Auger +--- + target/arm/cpu.c | 82 ++++++++++++++++++++++++++++++++++++++++++ + target/arm/cpu.h | 1 + + target/arm/internals.h | 53 +++++++++++++++++++++++++++ + 3 files changed, 136 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index e2b2337399..9f7938d8fa 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -172,6 +172,82 @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, + QLIST_INSERT_HEAD(&cpu->el_change_hooks, entry, node); + } + ++static ARMCPRegMigTolerance *find_mig_tolerance(ARMCPU *cpu, uint64_t kvmidx) ++{ ++ ARMCPRegMigTolerance *t; ++ QLIST_FOREACH(t, &cpu->cpreg_mig_tolerances, node) { ++ if (t->kvmidx == kvmidx) { ++ return t; ++ } ++ } ++ return NULL; ++} ++ ++void arm_register_cpreg_mig_tolerance(ARMCPU *cpu, uint64_t kvmidx, ++ uint64_t mask, uint64_t value, ++ ARMCPRegMigToleranceType type) ++{ ++ ARMCPRegMigTolerance *entry; ++ ++ /* make sure the kvmidx has not tolerance already registered */ ++ assert(!find_mig_tolerance(cpu, kvmidx)); ++ ++ assert(type == ToleranceNotOnBothEnds || ++ type == ToleranceOnlySrcTestValue); ++ ++ entry = g_new0(ARMCPRegMigTolerance, 1); ++ ++ entry->kvmidx = kvmidx; ++ entry->mask = mask; ++ entry->value = value; ++ entry->type = type; ++ ++ QLIST_INSERT_HEAD(&cpu->cpreg_mig_tolerances, entry, node); ++} ++ ++bool arm_cpu_match_cpreg_mig_tolerance(ARMCPU *cpu, uint64_t kvmidx, ++ uint64_t vmstate_value, uint64_t local_value, ++ ARMCPRegMigToleranceType type) ++{ ++ ARMCPRegMigTolerance *t = find_mig_tolerance(cpu, kvmidx); ++ uint64_t diff, diff_outside_mask, field; ++ ++ if (!t || t->type != type) { ++ return false; ++ } ++ ++ if (type == ToleranceNotOnBothEnds) { ++ return true; ++ } ++ ++ if (type == ToleranceOnlySrcTestValue && ++ ((vmstate_value & t->mask) == t->value)) { ++ return true; ++ } ++ ++ /* Need to check the mask */ ++ diff = vmstate_value ^ local_value; ++ diff_outside_mask = diff & ~t->mask; ++ ++ if (diff_outside_mask) { ++ /* there are differences outside of the mask */ ++ return false; ++ } ++ if (type == ToleranceDiffInMask) { ++ /* differences only in the field, tolerance matched */ ++ return true; ++ } ++ /* need to compare field value against authorized ones */ ++ field = vmstate_value & t->mask; ++ if (type == ToleranceFieldLT && (field < t->value)) { ++ return true; ++ } ++ if (type == ToleranceFieldGT && (field > t->value)) { ++ return true; ++ } ++ return false; ++} ++ + static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque) + { + /* Reset a single ARMCPRegInfo register */ +@@ -1455,6 +1531,7 @@ static void arm_cpu_initfn(Object *obj) + + QLIST_INIT(&cpu->pre_el_change_hooks); + QLIST_INIT(&cpu->el_change_hooks); ++ QLIST_INIT(&cpu->cpreg_mig_tolerances); + + #ifdef CONFIG_USER_ONLY + # ifdef TARGET_AARCH64 +@@ -1895,6 +1972,7 @@ static void arm_cpu_finalizefn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); + ARMELChangeHook *hook, *next; ++ ARMCPRegMigTolerance *t, *n; + + g_hash_table_destroy(cpu->cp_regs); + +@@ -1906,6 +1984,10 @@ static void arm_cpu_finalizefn(Object *obj) + QLIST_REMOVE(hook, node); + g_free(hook); + } ++ QLIST_FOREACH_SAFE(t, &cpu->cpreg_mig_tolerances, node, n) { ++ QLIST_REMOVE(t, node); ++ g_free(t); ++ } + #ifndef CONFIG_USER_ONLY + if (cpu->pmu_timer) { + timer_free(cpu->pmu_timer); +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index dc0da8b0ae..e5dbc5a3f9 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1126,6 +1126,7 @@ struct ArchCPU { + + QLIST_HEAD(, ARMELChangeHook) pre_el_change_hooks; + QLIST_HEAD(, ARMELChangeHook) el_change_hooks; ++ QLIST_HEAD(, ARMCPRegMigTolerance) cpreg_mig_tolerances; + + int32_t node_id; /* NUMA node this CPU belongs to */ + +diff --git a/target/arm/internals.h b/target/arm/internals.h +index 08e2acdb99..b8444aa8ab 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -1984,4 +1984,57 @@ bool arm_pan_enabled(CPUARMState *env); + /* Compare uint64_t for qsort and bsearch. */ + int compare_u64(const void *a, const void *b); + ++typedef enum { ++ ToleranceNotOnBothEnds, ++ ToleranceOnlySrcTestValue, ++ ToleranceDiffInMask, ++ ToleranceFieldLT, ++ ToleranceFieldGT, ++} ARMCPRegMigToleranceType; ++ ++typedef struct ARMCPRegMigTolerance { ++ uint64_t kvmidx; ++ uint64_t mask; ++ uint64_t value; ++ ARMCPRegMigToleranceType type; ++ QLIST_ENTRY(ARMCPRegMigTolerance) node; ++} ARMCPRegMigTolerance; ++ ++/** ++ * arm_register_cpreg_mig_tolerance: ++ * Register a migration tolerance wrt one given cpreg identified by its ++ * @kvmidx. Calling this function twice for the same @kvmidx is a ++ * programming error and will cause an assertion failure. ++ * ++ * @cpu: vcpu to apply the migration tolerance on ++ * @kvmidx: kvm index of the cpreg the tolerance applies to ++ * @mask: bitmask where a difference is tolerated ++ * (relevant with ToleranceDiffInMask) ++ * @value: value the bitmask field is compared with ++ * (relevant with ToleranceFieldLT and ToleranceFieldGT) ++ * @type: type of the migration tolerance: ++ * - ToleranceNotOnBothEnds (cpreg index is allowed to be only present ++ * on one end) ++ * - ToleranceOnlySrcTestValue (cpreg index is allowed to be only ++ * present in source if its value @mask field matches @value) ++ * - ToleranceDiffInMask (mismatch in cpreg values are only tolerated ++ * if differences are within @mask) ++ * - ToleranceFieldLT (mismatch in cpreg values are only tolerated ++ * if incoming @bitmask field value is less than @value) ++ * - ToleranceFieldGT (mismatch in cpreg values are only tolerated ++ * if incoming @bitmask field value is greater than @value) ++ */ ++void arm_register_cpreg_mig_tolerance(ARMCPU *cpu, uint64_t kvmidx, ++ uint64_t mask, uint64_t value, ++ ARMCPRegMigToleranceType type); ++ ++/** ++ * arm_cpu_match_cpreg_mig_tolerance: ++ * Check whether a tolerance of type @type exists for a given @kvmidx ++ * and the tolerance criterion is satisfied ++ */ ++bool arm_cpu_match_cpreg_mig_tolerance(ARMCPU *cpu, uint64_t kvmidx, ++ uint64_t vmstate_value, uint64_t local_value, ++ ARMCPRegMigToleranceType type); ++ + #endif diff --git a/0353-target-arm-machine-Handle-ToleranceNotOnBothEnds-mig.patch b/0353-target-arm-machine-Handle-ToleranceNotOnBothEnds-mig.patch new file mode 100644 index 0000000..df0495f --- /dev/null +++ b/0353-target-arm-machine-Handle-ToleranceNotOnBothEnds-mig.patch @@ -0,0 +1,84 @@ +From 9059108a55366e6337b67f7f101340c4d2a141b5 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:52 +0200 +Subject: [PATCH] target/arm/machine: Handle ToleranceNotOnBothEnds migration + tolerances + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [11/16] 26354a54c0d479bd06bdbb1e8d6ec47d7a4688e8 (eauger1/centos-qemu-kvm) + +If there is a mismatch between the cpreg indexes found on both ends, +check whether a tolerance was registered for the given kvmidx. If any, +silence warning/errors. + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260420140552.104369-3-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit 5e65e7aa4a1b57b1dbfcecec629c9e3fb55e94b1) +Signed-off-by: Eric Auger +--- + target/arm/machine.c | 21 +++++++++++++++------ + target/arm/trace-events | 2 ++ + 2 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/target/arm/machine.c b/target/arm/machine.c +index e0447083ee..0d749fc8fb 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -975,25 +975,34 @@ static void handle_cpreg_missing_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx + { + g_autofree gchar *name = print_register_name(kvmidx); + ++ if (arm_cpu_match_cpreg_mig_tolerance(cpu, kvmidx, ++ 0, 0, ToleranceNotOnBothEnds)) { ++ trace_tolerate_cpreg_missing_in_incoming_stream(name); ++ return; ++ } + warn_report("%s: %s " + "expected by the destination but not in the incoming stream: " + "skip it", __func__, name); + } + + /* +- * Handle the situation where @kvmidx is in the incoming stream +- * but not on destination. This currently fails the migration but +- * we plan to accomodate some exceptions, hence the boolean returned value. ++ * Handle the situation where @kvmidx is in the incoming ++ * stream but not on destination. This fails the migration if ++ * no cpreg mig tolerance is matched for this @kvmidx ++ * Return true if the migration should eventually fail + */ + static bool handle_cpreg_only_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) + { + g_autofree gchar *name = print_register_name(kvmidx); +- bool fail = true; + ++ if (arm_cpu_match_cpreg_mig_tolerance(cpu, kvmidx, ++ 0, 0, ToleranceNotOnBothEnds)) { ++ trace_tolerate_cpreg_only_in_incoming_stream(name); ++ return false; ++ } + error_report("%s: %s in the incoming stream but unknown on the " + "destination: fail migration", __func__, name); +- +- return fail; ++ return true; + } + + static int cpu_post_load(void *opaque, int version_id) +diff --git a/target/arm/trace-events b/target/arm/trace-events +index 4e2502af9f..062a011881 100644 +--- a/target/arm/trace-events ++++ b/target/arm/trace-events +@@ -16,3 +16,5 @@ kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is + + # machine.c + cpu_post_load(uint32_t cpreg_vmstate_array_len, uint32_t cpreg_array_len) "cpreg_vmstate_array_len=%d cpreg_array_len=%d" ++tolerate_cpreg_missing_in_incoming_stream(char *name) "%s is missing in incoming stream but this is explicitly tolerated" ++tolerate_cpreg_only_in_incoming_stream(char *name) "%s is in incoming stream but not on destination but this is explicitly tolerated" diff --git a/0354-target-arm-machine-Handle-ToleranceOnlySrcTestValue-.patch b/0354-target-arm-machine-Handle-ToleranceOnlySrcTestValue-.patch new file mode 100644 index 0000000..169a62e --- /dev/null +++ b/0354-target-arm-machine-Handle-ToleranceOnlySrcTestValue-.patch @@ -0,0 +1,71 @@ +From ed4122a9a79520987cbd51100770c03726d9c7d8 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:53 +0200 +Subject: [PATCH] target/arm/machine: Handle ToleranceOnlySrcTestValue + migration tolerance + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [12/16] df44347fd53723ee81c4167e82bb85a15b94ac23 (eauger1/centos-qemu-kvm) + +Pass the value of the incoming register to +handle_cpreg_only_in_incoming_stream and check whether there is +a matching ToleranceOnlySrcTestValue tolerance. + +Signed-off-by: Eric Auger +Message-id: 20260420140552.104369-4-eric.auger@redhat.com +Signed-off-by: Peter Maydell +Reviewed-by: Peter Maydell +(cherry picked from commit 9d2e717da4f4822ddb89c1ae78a0afd328a1f554) +Signed-off-by: Eric Auger +--- + target/arm/machine.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/target/arm/machine.c b/target/arm/machine.c +index 0d749fc8fb..b75097f371 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -991,12 +991,15 @@ static void handle_cpreg_missing_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx + * no cpreg mig tolerance is matched for this @kvmidx + * Return true if the migration should eventually fail + */ +-static bool handle_cpreg_only_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) ++static bool ++handle_cpreg_only_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx, uint64_t value) + { + g_autofree gchar *name = print_register_name(kvmidx); + + if (arm_cpu_match_cpreg_mig_tolerance(cpu, kvmidx, +- 0, 0, ToleranceNotOnBothEnds)) { ++ 0, 0, ToleranceNotOnBothEnds) || ++ arm_cpu_match_cpreg_mig_tolerance(cpu, kvmidx, ++ value, 0, ToleranceOnlySrcTestValue)) { + trace_tolerate_cpreg_only_in_incoming_stream(name); + return false; + } +@@ -1049,7 +1052,9 @@ static int cpu_post_load(void *opaque, int version_id) + } + if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) { + fail = handle_cpreg_only_in_incoming_stream(cpu, +- cpu->cpreg_vmstate_indexes[v++]); ++ cpu->cpreg_vmstate_indexes[v], ++ cpu->cpreg_vmstate_values[v]); ++ v++; + continue; + } + /* matching register, copy the value over */ +@@ -1072,7 +1077,8 @@ static int cpu_post_load(void *opaque, int version_id) + */ + for ( ; v < cpu->cpreg_vmstate_array_len; v++) { + fail = handle_cpreg_only_in_incoming_stream(cpu, +- cpu->cpreg_vmstate_indexes[v]); ++ cpu->cpreg_vmstate_indexes[v], ++ cpu->cpreg_vmstate_values[v]); + } + if (fail) { + return -1; diff --git a/0355-target-arm-cpu64-Mitigate-migration-failures-due-to-.patch b/0355-target-arm-cpu64-Mitigate-migration-failures-due-to-.patch new file mode 100644 index 0000000..86f4a1f --- /dev/null +++ b/0355-target-arm-cpu64-Mitigate-migration-failures-due-to-.patch @@ -0,0 +1,88 @@ +From 77103c408f6011cb662bfa80a6246cc3d8201789 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:54 +0200 +Subject: [PATCH] target/arm/cpu64: Mitigate migration failures due to spurious + TCR_EL1, PIRE0_EL1 and PIR_EL1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [13/16] 90857210d7a915351c637756650071ff44f8d378 (eauger1/centos-qemu-kvm) + +Conflicts: contextual conflict in target/arm/cpu64.c as cpu local +variable is declared in the #if defined(CONFIG_KVM) and not at the top + +Before linux v6.13 those registers were erroneously unconditionally +exposed and this was fixed by commits: +- 0fcb4eea5345 ("KVM: arm64: Hide TCR2_EL1 from userspace when + disabled for guests") +- a68cddbe47ef ("KVM: arm64: Hide S1PIE registers from userspace + when disabled for guests") +in v6.13. + +This means if we migrate from an old kernel host to a >= 6.13 kernel +host, migration currently fails. + +Declare cpreg migration tolerance for those registers. + +Signed-off-by: Eric Auger +Reviewed-by: Sebastian Ott +Reviewed-by: Peter Maydell +Message-id: 20260420140552.104369-5-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit 113ed8e53c08a46af2d3307ece846caf5a719f99) +Signed-off-by: Eric Auger +--- + target/arm/cpu64.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 051d5d653b..820d2542fa 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -762,10 +762,39 @@ static void aarch64_a53_initfn(Object *obj) + } + #endif + ++#if defined(CONFIG_KVM) ++static void kvm_arm_set_cpreg_mig_tolerances(ARMCPU *cpu) ++{ ++ /* ++ * Registers that may be in the incoming stream and not exposed ++ * on the destination ++ */ ++ ++ /* ++ * TCR_EL1 was erroneously unconditionnally exposed before linux v6.13. ++ * See commit 0fcb4eea5345 ("KVM: arm64: Hide TCR2_EL1 from userspace ++ * when disabled for guests") ++ */ ++ arm_register_cpreg_mig_tolerance(cpu, ARM64_SYS_REG(3, 0, 2, 0, 3), ++ 0, 0, ToleranceNotOnBothEnds); ++ /* ++ * PIRE0_EL1 and PIR_EL1 were erroneously unconditionnally exposed ++ * before linux v6.13. See commit a68cddbe47ef ("KVM: arm64: Hide ++ * S1PIE registers from userspace when disabled for guests") ++ */ ++ arm_register_cpreg_mig_tolerance(cpu, ARM64_SYS_REG(3, 0, 10, 2, 2), ++ 0, 0, ToleranceNotOnBothEnds); ++ arm_register_cpreg_mig_tolerance(cpu, ARM64_SYS_REG(3, 0, 10, 2, 3), ++ 0, 0, ToleranceNotOnBothEnds); ++} ++#endif ++ + static void aarch64_host_initfn(Object *obj) + { + #if defined(CONFIG_KVM) + ARMCPU *cpu = ARM_CPU(obj); ++ ++ kvm_arm_set_cpreg_mig_tolerances(cpu); + kvm_arm_set_cpu_features_from_host(cpu); + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + aarch64_add_sve_properties(obj); diff --git a/0356-target-arm-cpu64-Define-cpreg-migration-tolerance-fo.patch b/0356-target-arm-cpu64-Define-cpreg-migration-tolerance-fo.patch new file mode 100644 index 0000000..6d076ea --- /dev/null +++ b/0356-target-arm-cpu64-Define-cpreg-migration-tolerance-fo.patch @@ -0,0 +1,55 @@ +From a4ed027e8feb7625bd97f9c13600b490e2427291 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:55 +0200 +Subject: [PATCH] target/arm/cpu64: Define cpreg migration tolerance for + KVM_REG_ARM_VENDOR_HYP_BMAP_2 + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [14/16] 2289633dd2eadbde2e57a19da4259fa7c7c00013 (eauger1/centos-qemu-kvm) + +KVM_REG_ARM_VENDOR_HYP_BMAP_2 pseudo FW register is exposed +from v6.15 onwards. Backward migration from a >= v6.15 to an older +kernel would fail without cpreg migration tolerance definition +for this register. If the register is present on source but not +on destination, its value must be checked to make sure it matches +the reset value, ie. 0, meaning no service is exposed to the guest, +hence the choice of a ToleranceOnlySrcTestValue migration +tolerance. + +Signed-off-by: Eric Auger +Reviewed-by: Peter Maydell +Message-id: 20260420140552.104369-6-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit 6dd8be31f8fbbeba65a80b1e96c7331886c6f6d5) +Signed-off-by: Eric Auger +--- + target/arm/cpu64.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 820d2542fa..98d9f34550 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -786,6 +786,17 @@ static void kvm_arm_set_cpreg_mig_tolerances(ARMCPU *cpu) + 0, 0, ToleranceNotOnBothEnds); + arm_register_cpreg_mig_tolerance(cpu, ARM64_SYS_REG(3, 0, 10, 2, 3), + 0, 0, ToleranceNotOnBothEnds); ++ ++ /* ++ * KVM_REG_ARM_VENDOR_HYP_BMAP_2 pseudo FW register is exposed ++ * from v6.15 onwards. Backward migration from a >= v6.15 to an older ++ * kernel would fail without cpreg migration tolerance definition. ++ * If the register is present on source but not on destination, make ++ * sure it has its reset value, ie. 0, meaning no service is exposed ++ * to the guest. ++ */ ++ arm_register_cpreg_mig_tolerance(cpu, KVM_REG_ARM_FW_FEAT_BMAP_REG(3), ++ UINT64_MAX, 0, ToleranceOnlySrcTestValue); + } + #endif + diff --git a/0357-target-arm-helper-Define-cpreg-migration-tolerance-f.patch b/0357-target-arm-helper-Define-cpreg-migration-tolerance-f.patch new file mode 100644 index 0000000..910dbed --- /dev/null +++ b/0357-target-arm-helper-Define-cpreg-migration-tolerance-f.patch @@ -0,0 +1,72 @@ +From 1d432ec5787507b2c25eca46ce95e3560289c00f Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:56 +0200 +Subject: [PATCH] target/arm/helper: Define cpreg migration tolerance for + DGBDTR_EL0 + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [15/16] 4c159a6da8530899c605c9aa81c99a06be2f0819 (eauger1/centos-qemu-kvm) + +We want to remove AArch32 DBGDTRTX which was erroneously exposed. +This was attempted by 655659a74a36b ("target/arm: Correct encoding +of Debug Communications Channel registers") but it was discovered +that the removal of this debug register broke forward migration on +TCG. Now we have the cpreg migration tolerance infrastructure, we +can declare one for the DBGDTRTX. This allow to revert the reinstate +patch. + +Signed-off-by: Eric Auger +Reviewed-by: Sebastian Ott +Reviewed-by: Peter Maydell +Message-id: 20260420140552.104369-7-eric.auger@redhat.com +[PMM: revised comment, included note about when we can drop + the workaround] +Signed-off-by: Peter Maydell +(cherry picked from commit 234b3eaddd4ff08b8b62d563742e37f7bb6486bd) +Signed-off-by: Eric Auger +--- + target/arm/helper.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 5e643ed6b2..0deb2bd760 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -6129,9 +6129,32 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .fgt = FGT_CLIDR_EL1, + .resetvalue = GET_IDREG(isar, CLIDR) + }; ++ uint64_t dbgtr_el0_kvmidx = ++ cpreg_to_kvm_id(ENCODE_CP_REG(14, 0, 1, 0, 5, 3, 0)); ++ + define_one_arm_cp_reg(cpu, &clidr); + define_arm_cp_regs(cpu, v7_cp_reginfo); + define_debug_regs(cpu); ++ /* ++ * We used to incorrectly expose a non-existent AArch32 "DBGDTRTX" ++ * register with this encoding. This has been fixed by commit ++ * 655659a74a36 ("target/arm: Correct encoding of Debug ++ * Communications Channel registers") by the introduction of correct ++ * separate cpreg definitions for AA64 and AA32 versions. However, ++ * the old cpreg definition couldn't be removed without breaking ++ * migration, so commit 4f2b82f604 reinstated the bogus encoding ++ * for migration data only. ++ * ++ * Now that we have migration tolerance infrastructure, we can use ++ * this to allow forward migration from the buggy QEMU versions, ++ * accepting and ignoring the bogus register if it is in the ++ * source data. QEMU 11.0 was the last version that sent the ++ * bogus encoding, so this workaround can be removed at the point ++ * where we no longer care about migration from that version ++ * (i.e. when we remove the "virt-11.0" machine type). ++ */ ++ arm_register_cpreg_mig_tolerance(cpu, dbgtr_el0_kvmidx, ++ 0, 0, ToleranceNotOnBothEnds); + } else { + define_arm_cp_regs(cpu, not_v7_cp_reginfo); + } diff --git a/0358-Revert-target-arm-Reinstate-bogus-AArch32-DBGDTRTX-r.patch b/0358-Revert-target-arm-Reinstate-bogus-AArch32-DBGDTRTX-r.patch new file mode 100644 index 0000000..3ef5e6d --- /dev/null +++ b/0358-Revert-target-arm-Reinstate-bogus-AArch32-DBGDTRTX-r.patch @@ -0,0 +1,77 @@ +From dc13639a241cb3f89aabb52c552802de5e174ffe Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 20 Apr 2026 16:03:57 +0200 +Subject: [PATCH] Revert "target/arm: Reinstate bogus AArch32 DBGDTRTX register + for migration compat" + +RH-Author: Eric Auger +RH-MergeRequest: 488: [rhel-10] Backport cross-kernel migration failure mitigation series +RH-Jira: RHEL-174858 +RH-Acked-by: Mohammadfaiz Bawa +RH-Acked-by: Sebastian Ott +RH-Acked-by: Gavin Shan +RH-Commit: [16/16] 60be5ef3f6fe516b480e578cd610618d180a9655 (eauger1/centos-qemu-kvm) + +This reverts commit 4f2b82f60431 ("target/arm: Reinstate bogus AArch32 +DBGDTRTX register for migration compat). We don't need that commit +anymore as the AArch32 DBGDTRTX register is declared to +be safe to ignore in the incoming migration stream. + +Signed-off-by: Eric Auger +Reviewed-by: Sebastian Ott +Reviewed-by: Peter Maydell +Message-id: 20260420140552.104369-8-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit 202126dcb9d6261c38e629799265defeb3260d25) +Signed-off-by: Eric Auger +--- + target/arm/debug_helper.c | 29 ----------------------------- + 1 file changed, 29 deletions(-) + +diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c +index 579516e154..aee06d4d42 100644 +--- a/target/arm/debug_helper.c ++++ b/target/arm/debug_helper.c +@@ -940,13 +940,6 @@ static void dbgclaimclr_write(CPUARMState *env, const ARMCPRegInfo *ri, + env->cp15.dbgclaim &= ~(value & 0xFF); + } + +-static CPAccessResult access_bogus(CPUARMState *env, const ARMCPRegInfo *ri, +- bool isread) +-{ +- /* Always UNDEF, as if this cpreg didn't exist */ +- return CP_ACCESS_UNDEFINED; +-} +- + static const ARMCPRegInfo debug_cp_reginfo[] = { + /* + * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped +@@ -1009,28 +1002,6 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { + .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 4, .opc2 = 0, + .access = PL0_RW, .accessfn = access_tdcc, + .type = ARM_CP_CONST, .resetvalue = 0 }, +- /* +- * This is not a real AArch32 register. We used to incorrectly expose +- * this due to a QEMU bug; to avoid breaking migration compatibility we +- * need to continue to provide it so that we don't fail the inbound +- * migration when it tells us about a sysreg that we don't have. +- * We set an always-fails .accessfn, which means that the guest doesn't +- * actually see this register (it will always UNDEF, identically to if +- * there were no cpreg definition for it other than that we won't print +- * a LOG_UNIMP message about it), and we set the ARM_CP_NO_GDB flag so the +- * gdbstub won't see it either. +- * (We can't just set .access = 0, because add_cpreg_to_hashtable() +- * helpfully ignores cpregs which aren't accessible to the highest +- * implemented EL.) +- * +- * TODO: implement a system for being able to describe "this register +- * can be ignored if it appears in the inbound stream"; then we can +- * remove this temporary hack. +- */ +- { .name = "BOGUS_DBGDTR_EL0", .state = ARM_CP_STATE_AA32, +- .cp = 14, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0, +- .access = PL0_RW, .accessfn = access_bogus, +- .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 }, + /* + * OSECCR_EL1 provides a mechanism for an operating system + * to access the contents of EDECCR. EDECCR is not implemented though, diff --git a/qemu-kvm.spec b/qemu-kvm.spec index b8c9a9d..4b391d4 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -143,7 +143,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \ Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 10.1.0 -Release: 18%{?rcrel}%{?dist}%{?cc_suffix}.1 +Release: 19%{?rcrel}%{?dist}%{?cc_suffix}.1 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped # Epoch 15 used for RHEL 8 # Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5) @@ -507,142 +507,23 @@ Patch338: 0338-hw-tpm-Simplify-tpm_ppi_enabled.patch Patch339: 0339-docs-specs-tpm-document-PPI-support-on-ARM64-virt.patch Patch340: 0340-hw-acpi-tpm-parameterize-PPI-base-address-in-tpm_bui.patch Patch341: 0341-hw-tpm-add-PPI-support-to-tpm-tis-device-for-ARM64-v.patch - - -# For RHEL-112882 - [DEV Task]: Assertion `core->delayed_causes == 0' failed with e1000e NIC -# For RHEL-119368 - [rhel10] Backport "arm/kvm: report registers we failed to set" -# For RHEL-116443 - qemu crash after hot-unplug disk from the multifunction enabled bus,crash point PCIDevice *vf = dev->exp.sriov_pf.vf[i] -# For RHEL-120253 - Backport fixes for PDCM and ARCH_CAPABILITIES migration incompatibility -# For RHEL-120253 - Backport fixes for PDCM and ARCH_CAPABILITIES migration incompatibility -# For RHEL-104009 - [IBM 10.2 FEAT] KVM: Enhance machine type definition to include CPI and PCI passthru capabilities (qemu) -# For RHEL-105823 - Add new -rhel10.2.0 machine type to qemu-kvm [s390x] -# For RHEL-73008 - [IBM 10.2 FEAT] KVM: Implement Control Program Identification (qemu) -# For RHEL-104009 - [IBM 10.2 FEAT] KVM: Enhance machine type definition to include CPI and PCI passthru capabilities (qemu) -# For RHEL-105823 - Add new -rhel10.2.0 machine type to qemu-kvm [s390x] -# For RHEL-73008 - [IBM 10.2 FEAT] KVM: Implement Control Program Identification (qemu) -# For RHEL-104009 - [IBM 10.2 FEAT] KVM: Enhance machine type definition to include CPI and PCI passthru capabilities (qemu) -# For RHEL-105823 - Add new -rhel10.2.0 machine type to qemu-kvm [s390x] -# For RHEL-73008 - [IBM 10.2 FEAT] KVM: Implement Control Program Identification (qemu) -# For RHEL-118810 - [RHEL 10.2] Windows 11 VM fails to boot up with ramfb='on' with QEMU 10.1 -# For RHEL-118810 - [RHEL 10.2] Windows 11 VM fails to boot up with ramfb='on' with QEMU 10.1 -# For RHEL-105826 - Add new -rhel10.2.0 machine type to qemu-kvm [aarch64] -# For RHEL-105828 - Add new -rhel10.2.0 machine type to qemu-kvm [x86_64] -# For RHEL-105826 - Add new -rhel10.2.0 machine type to qemu-kvm [aarch64] -# For RHEL-105828 - Add new -rhel10.2.0 machine type to qemu-kvm [x86_64] -# For RHEL-105826 - Add new -rhel10.2.0 machine type to qemu-kvm [aarch64] -# For RHEL-105828 - Add new -rhel10.2.0 machine type to qemu-kvm [x86_64] -# For RHEL-105826 - Add new -rhel10.2.0 machine type to qemu-kvm [aarch64] -# For RHEL-105828 - Add new -rhel10.2.0 machine type to qemu-kvm [x86_64] -# For RHEL-101929 - enable 'usb-bot' device for proper support of USB CD-ROM drives via libvirt -# For RHEL-120116 - CVE-2025-11234 qemu-kvm: VNC WebSocket handshake use-after-free [rhel-10.2] -# For RHEL-120116 - CVE-2025-11234 qemu-kvm: VNC WebSocket handshake use-after-free [rhel-10.2] -# For RHEL-126573 - VFIO migration using multifd should be disabled by default -# For RHEL-67323 - [aarch64] Support ACPI based PCI hotplug on ARM -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-73800 - NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1 -# For RHEL-126708 - [RHEL 10]snp guest fail to boot with hugepage -# For RHEL-126708 - [RHEL 10]snp guest fail to boot with hugepage -# For RHEL-128085 - VM crashes during boot when virtio device is attached through vfio_ccw -# For RHEL-130704 - [rhel10] Fix the typo under vfio-pci device's enable-migration option -# For RHEL-120115 - The vf nic created using the IGB emulated nic can not obtain ip address -# For RHEL-130478 - Migration from RHEL 10.2 to RHEL 10.1 with virt-rhel10.0.0 machine type fails on Grace -# For RHEL-129540 - Assertion failure on drain with iothread and I/O load -# For RHEL-121543 - The VM hit io error when do S3-PR integration on the pass-through failover multipath device -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-134212 - [RHEL10.2] L1VH qemu downstream initial merge RHEL10.2 -# For RHEL-110003 - Expose block limits of block nodes in QMP and qemu-img -# For RHEL-110003 - Expose block limits of block nodes in QMP and qemu-img -# For RHEL-110003 - Expose block limits of block nodes in QMP and qemu-img -# For RHEL-110003 - Expose block limits of block nodes in QMP and qemu-img -# For RHEL-111853 - [Intel 10.0 FEAT] [SPR] TDX: Virt-QEMU: QEMU Support [rhel-10] -# For RHEL-108142 - QEMU crashes when stopping source VM during live migration -# For RHEL-126707 - [qemu, rhel-10] increase default TSEG size -# For RHEL-126707 - [qemu, rhel-10] increase default TSEG size -# For RHEL-139028 - Intel IOMMU VM freezes: "call_irq_handler: 3.37 No irq handler for vector"[rhel-10.2] -# For RHEL-111853 - [Intel 10.0 FEAT] [SPR] TDX: Virt-QEMU: QEMU Support [rhel-10] -# For RHEL-79118 - [network-storage][rbd][core-dump]installation of guest failed sometimes with multiqueue enabled [rhel10] -# For RHEL-79118 - [network-storage][rbd][core-dump]installation of guest failed sometimes with multiqueue enabled [rhel10] -# For RHEL-79118 - [network-storage][rbd][core-dump]installation of guest failed sometimes with multiqueue enabled [rhel10] -# For RHEL-79118 - [network-storage][rbd][core-dump]installation of guest failed sometimes with multiqueue enabled [rhel10] -# For RHEL-79118 - [network-storage][rbd][core-dump]installation of guest failed sometimes with multiqueue enabled [rhel10] -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-143785 - backport support for GSO over UDP tunnel offload -# For RHEL-147425 - virtiofs: processes become stuck in request_wait_answer on virtiofs mounts -# For RHEL-132749 - Migrate SCSI PR state and preempt reservation upon live migration -# For RHEL-132749 - Migrate SCSI PR state and preempt reservation upon live migration -# For RHEL-132749 - Migrate SCSI PR state and preempt reservation upon live migration -# For RHEL-132749 - Migrate SCSI PR state and preempt reservation upon live migration -# For RHEL-132749 - Migrate SCSI PR state and preempt reservation upon live migration -# For RHEL-134989 - Hotplugged interface device can not be shown in the guest -# For RHEL-146584 - [RHEL-10.2][ARM]: Unable to Check the mem prefetched size on Guest -# For RHEL-153058 - Qemu crashes with "double free" during restore --reset-nvram with uefi-vars secure boot -# For RHEL-144004 - [rhel-10] Regression in BLOCK_IO_ERROR event delivery with (w|r)error setting of 'stop' or 'enospc' due to event rate limiting -# For RHEL-155601 - Mirror job can miss writes during startup, corrupting the copy [rhel-10.2] -# For RHEL-158224 - qemu-kvm: disk writes of fewer bytes than requested is a retry condition, not necessarily an indication of ENOSPC [rhel-10.2] -# For RHEL-158224 - qemu-kvm: disk writes of fewer bytes than requested is a retry condition, not necessarily an indication of ENOSPC [rhel-10.2] -# For RHEL-158224 - qemu-kvm: disk writes of fewer bytes than requested is a retry condition, not necessarily an indication of ENOSPC [rhel-10.2] -# For RHEL-158224 - qemu-kvm: disk writes of fewer bytes than requested is a retry condition, not necessarily an indication of ENOSPC [rhel-10.2] -# For RHEL-114231 - Add stats-intervals support to --blockdev -# For RHEL-114231 - Add stats-intervals support to --blockdev -# For RHEL-158212 - qemu-kvm doesn't retry SG-IO on 05/25/00 (ILLEGAL REQUEST / LOGICAL UNIT NOT SUPPORTED) [rhel-10.3] -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass -# For RHEL-112608 - [ARM64] Windows 11 VM should install without TPM Bypass +Patch342: 0342-hw-vfio-iommufd-Control-dirty-tracking-for-nesting-p.patch +Patch343: 0343-vmstate-Introduce-VMSTATE_VARRAY_INT32_ALLOC.patch +Patch344: 0344-target-arm-Move-compare_u64-to-helper.c.patch +Patch345: 0345-target-arm-Convert-init_cpreg_list-to-g_hash_table_f.patch +Patch346: 0346-target-arm-machine-Use-VMSTATE_VARRAY_INT32_ALLOC-fo.patch +Patch347: 0347-target-arm-kvm-Export-kvm_print_register_name.patch +Patch348: 0348-target-arm-kvm-Tweak-print_register_name-for-arm64-s.patch +Patch349: 0349-target-arm-machine-Trace-cpreg-names-which-do-not-ma.patch +Patch350: 0350-target-arm-machine-Trace-all-register-mismatches.patch +Patch351: 0351-target-arm-machine-Fix-detection-of-unknown-incoming.patch +Patch352: 0352-target-arm-cpu-Introduce-the-infrastructure-for-cpre.patch +Patch353: 0353-target-arm-machine-Handle-ToleranceNotOnBothEnds-mig.patch +Patch354: 0354-target-arm-machine-Handle-ToleranceOnlySrcTestValue-.patch +Patch355: 0355-target-arm-cpu64-Mitigate-migration-failures-due-to-.patch +Patch356: 0356-target-arm-cpu64-Define-cpreg-migration-tolerance-fo.patch +Patch357: 0357-target-arm-helper-Define-cpreg-migration-tolerance-f.patch +Patch358: 0358-Revert-target-arm-Reinstate-bogus-AArch32-DBGDTRTX-r.patch %if %{have_clang} BuildRequires: clang @@ -1722,6 +1603,13 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %changelog +* Wed Jun 03 2026 Miroslav Rezanina - 10.1.0-19.el10nv.1 +- backport Control dirty tracking for nesting parent HWPT +- Resolves: VOYAGER-857 + +* Tue May 26 2026 Miroslav Rezanina - 10.1.0-19 +- Backport cross-kernel migration failure mitigation series + * Thu May 14 2026 Miroslav Rezanina - 10.1.0-18.el10nv.1 - CMDQV v4 and other GPU passthrough add-ons - Resolves: VOYAGER-15