From 7bff0233ecbb794e74ee6072e3da821839257ead Mon Sep 17 00:00:00 2001 From: LiQian Date: Tue, 15 Jul 2025 14:44:46 +0800 Subject: [PATCH] phytium:add phytium-v model to support live migration Add interfaces that can be used to determine the cpu platform. Add phytium-v as a minimal set of phytium server features. This model which is commonly used in live migration. Support for migration between phytium and kp920 when using phytium-v cpu model. Signed-off-by: Peng Mengguang Signed-off-by: LiQian --- ...d-interfaces-to-read-midr-on-aarch64.patch | 173 +++++++++++++ .../0027-cpu-add-phytium-v-cpu-support.patch | 239 ++++++++++++++++++ ...-migration-between-phytium-and-kp920.patch | 177 +++++++++++++ SPECS/qemu-kvm.spec | 14 +- 4 files changed, 602 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0026-util-add-interfaces-to-read-midr-on-aarch64.patch create mode 100644 SOURCES/0027-cpu-add-phytium-v-cpu-support.patch create mode 100644 SOURCES/0028-support-vm-live-migration-between-phytium-and-kp920.patch diff --git a/SOURCES/0026-util-add-interfaces-to-read-midr-on-aarch64.patch b/SOURCES/0026-util-add-interfaces-to-read-midr-on-aarch64.patch new file mode 100644 index 0000000..d54bc98 --- /dev/null +++ b/SOURCES/0026-util-add-interfaces-to-read-midr-on-aarch64.patch @@ -0,0 +1,173 @@ +From 7857a2c88320e61d7c29c43c8f0fee8ff12733b5 Mon Sep 17 00:00:00 2001 +From: LiQian +Date: Mon, 14 Jul 2025 17:36:20 +0800 +Subject: [PATCH 1/3] util: add interfaces to read midr on aarch64 + + These interfaces can be used to determine the cpu platform. + +Signed-off-by: pengmengguang +Signed-off-by: LiQian +--- + include/qemu/aarch64-cpuid.h | 51 +++++++++++++++++++++++ + util/aarch64-cpuid.c | 78 ++++++++++++++++++++++++++++++++++++ + util/meson.build | 1 + + 3 files changed, 130 insertions(+) + create mode 100644 include/qemu/aarch64-cpuid.h + create mode 100644 util/aarch64-cpuid.c + +diff --git a/include/qemu/aarch64-cpuid.h b/include/qemu/aarch64-cpuid.h +new file mode 100644 +index 0000000000..ec68e6d575 +--- /dev/null ++++ b/include/qemu/aarch64-cpuid.h +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * aarch64-cpuid.h: Macros to identify the MIDR of aarch64. ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef QEMU_AARCH64_CPUID_H ++#define QEMU_AARCH64_CPUID_H ++ ++#define MIDR_REVISION_MASK 0xf ++#define MIDR_REVISION(midr) ((midr) & MIDR_REVISION_MASK) ++#define MIDR_PARTNUM_SHIFT 4 ++#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT) ++#define MIDR_PARTNUM(midr) \ ++ (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT) ++#define MIDR_ARCHITECTURE_SHIFT 16 ++#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT) ++#define MIDR_ARCHITECTURE(midr) \ ++ (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT) ++#define MIDR_VARIANT_SHIFT 20 ++#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT) ++#define MIDR_VARIANT(midr) \ ++ (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT) ++#define MIDR_IMPLEMENTOR_SHIFT 24 ++#define MIDR_IMPLEMENTOR_MASK (0xffU << MIDR_IMPLEMENTOR_SHIFT) ++#define MIDR_IMPLEMENTOR(midr) \ ++ (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT) ++#define MIDR_CPU_MODEL(imp, partnum) \ ++ (((imp) << MIDR_IMPLEMENTOR_SHIFT) | \ ++ (0xf << MIDR_ARCHITECTURE_SHIFT) | \ ++ ((partnum) << MIDR_PARTNUM_SHIFT)) ++ ++#define MIDR_CPU_VAR_REV(var, rev) \ ++ (((var) << MIDR_VARIANT_SHIFT) | (rev)) ++ ++#define MIDR_CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \ ++ MIDR_ARCHITECTURE_MASK) ++ ++#define ARM_CPU_IMP_PHYTIUM 0x70 ++#define PHYTIUM_CPU_PART_FTC662 0x662 ++#define PHYTIUM_CPU_PART_FTC663 0x663 ++#define PHYTIUM_CPU_PART_FTC862 0x862 ++ ++uint64_t qemu_read_cpuid_id(void); ++uint8_t qemu_read_cpuid_implementor(void); ++uint16_t qemu_read_cpuid_part_number(void); ++bool is_phytium_cpu(void); ++ ++#endif +diff --git a/util/aarch64-cpuid.c b/util/aarch64-cpuid.c +new file mode 100644 +index 0000000000..b316713e45 +--- /dev/null ++++ b/util/aarch64-cpuid.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Dealing with arm cpu identification information. ++ * ++ * Copyright (C) 2024 Phytium, Inc. ++ * ++ * Authors: ++ * Peng Meng Guang ++ * ++ * This work is licensed under the terms of the GNU LGPL, version 2.1 ++ * or later. See the COPYING.LIB file in the top-level directory. ++ */ ++ ++#include ++#include "qemu/osdep.h" ++#include "qemu-common.h" ++#include "qemu/cutils.h" ++#include "qemu/aarch64-cpuid.h" ++ ++#if defined(__aarch64__) ++uint64_t qemu_read_cpuid_id(void) ++{ ++#ifdef CONFIG_LINUX ++ const char *file = "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1"; ++ char *buf; ++ uint64_t midr = 0; ++ ++#define BUF_SIZE 32 ++ buf = g_malloc0(BUF_SIZE); ++ if (!buf) { ++ return 0; ++ } ++ ++ if (!g_file_get_contents(file, &buf, 0, NULL)) { ++ goto out; ++ } ++ ++ if (qemu_strtoul(buf, NULL, 0, &midr) < 0) { ++ goto out; ++ } ++ ++out: ++ g_free(buf); ++ ++ return midr; ++#else ++ return 0; ++#endif ++} ++ ++uint8_t qemu_read_cpuid_implementor(void) ++{ ++#ifdef CONFIG_LINUX ++ uint64_t aarch64_midr = qemu_read_cpuid_id(); ++ ++ return MIDR_IMPLEMENTOR(aarch64_midr); ++#else ++ return 0; ++#endif ++} ++ ++uint16_t qemu_read_cpuid_part_number(void) ++{ ++#ifdef CONFIG_LINUX ++ uint64_t aarch64_midr = qemu_read_cpuid_id(); ++ ++ return MIDR_PARTNUM(aarch64_midr); ++#else ++ return 0; ++#endif ++} ++ ++bool is_phytium_cpu(void) ++{ ++ return qemu_read_cpuid_implementor() == ARM_CPU_IMP_PHYTIUM; ++} ++ ++#endif +diff --git a/util/meson.build b/util/meson.build +index b5f153b0e8..26386b8503 100644 +--- a/util/meson.build ++++ b/util/meson.build +@@ -49,6 +49,7 @@ util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c')) + util_ss.add(files('guest-random.c')) + util_ss.add(files('yank.c')) + util_ss.add(files('lockcnt.c')) ++util_ss.add(files('aarch64-cpuid.c')) + + if have_user + util_ss.add(files('selfmap.c')) +-- +2.33.0 + diff --git a/SOURCES/0027-cpu-add-phytium-v-cpu-support.patch b/SOURCES/0027-cpu-add-phytium-v-cpu-support.patch new file mode 100644 index 0000000..0866149 --- /dev/null +++ b/SOURCES/0027-cpu-add-phytium-v-cpu-support.patch @@ -0,0 +1,239 @@ +From cb3334fc71b059d4cc1c46d584f791e2fd45814a Mon Sep 17 00:00:00 2001 +From: LiQian +Date: Mon, 14 Jul 2025 17:41:57 +0800 +Subject: [PATCH 2/3] cpu: add phytium-v cpu support + + phytium-v as a minimal set of phytium server features. + this model is commonly used in live migration. + +Signed-off-by: pengmengguang +Signed-off-by: LiQian +--- + hw/arm/virt.c | 1 + + target/arm/cpu.h | 1 + + target/arm/cpu64.c | 37 +++++++++++++++++++ + target/arm/helper.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ + target/arm/kvm64.c | 15 ++++++++ + 5 files changed, 143 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 46c72a9611..9d23ec2616 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -261,6 +261,7 @@ static const char *valid_cpus[] = { + ARM_CPU_TYPE_NAME("a64fx"), + ARM_CPU_TYPE_NAME("host"), + ARM_CPU_TYPE_NAME("max"), ++ ARM_CPU_TYPE_NAME("phytium-v"), + }; + + static bool cpu_type_valid(const char *cpu) +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 8d2f496ef9..cceb2520f9 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -2934,6 +2934,7 @@ typedef struct ARMCPRegUserSpaceInfo { + #define REGUSERINFO_SENTINEL { .name = NULL } + + void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods); ++int modify_arm_vcpu_regs_for_phytium_v(ARMCPU *cpu); + + /* CPWriteFn that can be used to implement writes-ignored behaviour */ + void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 15245a60a8..0dd519241f 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -888,12 +888,49 @@ static void aarch64_a64fx_initfn(Object *obj) + /* TODO: Add A64FX specific HPC extension registers */ + } + ++static void aarch64_phytium_v_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ if (kvm_enabled()) { ++ kvm_arm_set_cpu_features_from_host(cpu); ++ } else { ++ uint64_t t; ++ ++ aarch64_a57_initfn(obj); ++ ++ /* ++ * Reset MIDR so the guest doesn't mistake our 'max' CPU type for a real ++ * one and try to apply errata workarounds or use impdef features we ++ * don't provide. ++ * An IMPLEMENTER field of 0 means "reserved for software use"; ++ * ARCHITECTURE must be 0xf indicating "v7 or later, check ID registers ++ * to see which features are present"; ++ * the VARIANT, PARTNUM and REVISION fields are all implementation ++ * defined and we choose to define PARTNUM just in case guest ++ * code needs to distinguish this QEMU CPU from other software ++ * implementations, though this shouldn't be needed. ++ */ ++ t = FIELD_DP64(0, MIDR_EL1, IMPLEMENTER, 0x70); ++ t = FIELD_DP64(t, MIDR_EL1, ARCHITECTURE, 0xf); ++ t = FIELD_DP64(t, MIDR_EL1, PARTNUM, 0x662); ++ t = FIELD_DP64(t, MIDR_EL1, VARIANT, 0x1); ++ t = FIELD_DP64(t, MIDR_EL1, REVISION, 2); ++ cpu->midr = t; ++ } ++ ++ aarch64_add_sve_properties(obj); ++ object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, ++ cpu_max_set_sve_max_vq, NULL, NULL); ++} ++ + static const ARMCPUInfo aarch64_cpus[] = { + { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, + { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, + { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, + { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, + { .name = "max", .initfn = aarch64_max_initfn }, ++ { .name = "phytium-v", .initfn = aarch64_phytium_v_initfn }, + }; + + static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp) +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 9b317899a6..27384fb8d9 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -30,6 +30,7 @@ + #include "qapi/qapi-commands-machine-target.h" + #include "qapi/error.h" + #include "qemu/guest-random.h" ++#include "qemu/aarch64-cpuid.h" + #ifdef CONFIG_TCG + #include "arm_ldst.h" + #include "exec/cpu_ldst.h" +@@ -53,6 +54,94 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, + static void switch_mode(CPUARMState *env, int mode); + static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); + ++#ifdef TARGET_AARCH64 ++#define SYS_ID_PFR0_EL1 ARM64_SYS_REG(3, 0, 0, 1, 0) ++#define SYS_ID_PFR1_EL1 ARM64_SYS_REG(3, 0, 0, 1, 1) ++#define SYS_ID_PFR2_EL1 ARM64_SYS_REG(3, 0, 0, 3, 4) ++#define SYS_ID_DFR0_EL1 ARM64_SYS_REG(3, 0, 0, 1, 2) ++#define SYS_ID_MMFR0_EL1 ARM64_SYS_REG(3, 0, 0, 1, 4) ++#define SYS_ID_MMFR1_EL1 ARM64_SYS_REG(3, 0, 0, 1, 5) ++#define SYS_ID_MMFR2_EL1 ARM64_SYS_REG(3, 0, 0, 1, 6) ++#define SYS_ID_MMFR3_EL1 ARM64_SYS_REG(3, 0, 0, 1, 7) ++#define SYS_ID_MMFR4_EL1 ARM64_SYS_REG(3, 0, 0, 2, 6) ++#define SYS_ID_ISAR0_EL1 ARM64_SYS_REG(3, 0, 0, 2, 0) ++#define SYS_ID_ISAR1_EL1 ARM64_SYS_REG(3, 0, 0, 2, 1) ++#define SYS_ID_ISAR2_EL1 ARM64_SYS_REG(3, 0, 0, 2, 2) ++#define SYS_ID_ISAR3_EL1 ARM64_SYS_REG(3, 0, 0, 2, 3) ++#define SYS_ID_ISAR4_EL1 ARM64_SYS_REG(3, 0, 0, 2, 4) ++#define SYS_ID_ISAR5_EL1 ARM64_SYS_REG(3, 0, 0, 2, 5) ++#define SYS_ID_ISAR6_EL1 ARM64_SYS_REG(3, 0, 0, 2, 7) ++#define SYS_MVFR0_EL1 ARM64_SYS_REG(3, 0, 0, 3, 0) ++#define SYS_MVFR1_EL1 ARM64_SYS_REG(3, 0, 0, 3, 1) ++#define SYS_MVFR2_EL1 ARM64_SYS_REG(3, 0, 0, 3, 2) ++#define SYS_ID_AA64PFR0_EL1 ARM64_SYS_REG(3, 0, 0, 4, 0) ++#define SYS_ID_AA64PFR1_EL1 ARM64_SYS_REG(3, 0, 0, 4, 1) ++#define SYS_ID_AA64DFR0_EL1 ARM64_SYS_REG(3, 0, 0, 5, 0) ++#define SYS_ID_AA64ISAR0_EL1 ARM64_SYS_REG(3, 0, 0, 6, 0) ++#define SYS_ID_AA64ISAR1_EL1 ARM64_SYS_REG(3, 0, 0, 6, 1) ++#define SYS_ID_AA64MMFR0_EL1 ARM64_SYS_REG(3, 0, 0, 7, 0) ++#define SYS_ID_AA64MMFR1_EL1 ARM64_SYS_REG(3, 0, 0, 7, 1) ++#define SYS_ID_AA64MMFR2_EL1 ARM64_SYS_REG(3, 0, 0, 7, 2) ++ ++struct SysRegInfo { ++ const char *name; ++ uint64_t reg; ++ uint64_t value; ++}; ++ ++const struct SysRegInfo sys_regs_info[] = { ++ { "ID_PFR0_EL1", SYS_ID_PFR0_EL1, 0 }, ++ { "ID_PFR1_EL1", SYS_ID_PFR1_EL1, 0 }, ++ { "ID_PFR2_EL1", SYS_ID_PFR2_EL1, 0 }, ++ { "ID_DFR0_EL1", SYS_ID_DFR0_EL1, 0 }, ++ { "ID_MMFR0_EL1", SYS_ID_MMFR0_EL1, 0 }, ++ { "ID_MMFR1_EL1", SYS_ID_MMFR1_EL1, 0 }, ++ { "ID_MMFR2_EL1", SYS_ID_MMFR2_EL1, 0 }, ++ { "ID_MMFR3_EL1", SYS_ID_MMFR3_EL1, 0 }, ++ { "ID_MMFR4_EL1", SYS_ID_MMFR4_EL1, 0 }, ++ { "ID_ISAR0_EL1", SYS_ID_ISAR0_EL1, 0 }, ++ { "ID_ISAR1_EL1", SYS_ID_ISAR1_EL1, 0 }, ++ { "ID_ISAR2_EL1", SYS_ID_ISAR2_EL1, 0 }, ++ { "ID_ISAR3_EL1", SYS_ID_ISAR3_EL1, 0 }, ++ { "ID_ISAR4_EL1", SYS_ID_ISAR4_EL1, 0 }, ++ { "ID_ISAR5_EL1", SYS_ID_ISAR5_EL1, 0 }, ++ { "ID_ISAR6_EL1", SYS_ID_ISAR6_EL1, 0 }, ++ { "MVFR0_EL1", SYS_MVFR0_EL1, 0 }, ++ { "MVFR1_EL1", SYS_MVFR1_EL1, 0 }, ++ { "MVFR2_EL1", SYS_MVFR2_EL1, 0 }, ++ { "ID_AA64PFR0_EL1", SYS_ID_AA64PFR0_EL1, 0x01001111 }, ++ { "ID_AA64PFR1_EL1", SYS_ID_AA64PFR1_EL1, 0 }, ++ { "ID_AA64DFR0_EL1", SYS_ID_AA64DFR0_EL1, 0x10305106 }, ++ { "ID_AA64ISAR0_EL1", SYS_ID_AA64ISAR0_EL1, 0x10000 }, ++ { "ID_AA64ISAR1_EL1", SYS_ID_AA64ISAR1_EL1, 0 }, ++ { "ID_AA64MMFR0_EL1", SYS_ID_AA64MMFR0_EL1, 0x1124 }, ++ { "ID_AA64MMFR1_EL1", SYS_ID_AA64MMFR1_EL1, 0 }, ++ { "ID_AA64MMFR2_EL1", SYS_ID_AA64MMFR2_EL1, 0 }, ++}; ++ ++/* PHYTIUM : modify sys_regs for phytium-v. */ ++int modify_arm_vcpu_regs_for_phytium_v(ARMCPU *cpu) ++{ ++ int ret = 0; ++ CPUState *cs = CPU(cpu); ++ Object *obj = OBJECT(cpu); ++ ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj); ++ ++ if (NULL != acc->info && 0 == strcmp(acc->info->name, "phytium-v")) { ++ uint64_t val = 0; ++ for (int i = 0; i < ARRAY_SIZE(sys_regs_info); i++) { ++ val = sys_regs_info[i].value; ++ ret = kvm_set_one_reg(cs, sys_regs_info[i].reg, &val); ++ if (ret) { ++ break; ++ } ++ } ++ } ++ ++ return ret; ++} ++#endif /* TARGET_AARCH64 */ ++ + static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + assert(ri->fieldoffset); +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index e790d6c9a5..d68f4e35de 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -32,6 +32,7 @@ + #include "hw/acpi/acpi.h" + #include "hw/acpi/ghes.h" + #include "hw/arm/virt.h" ++#include "qemu/aarch64-cpuid.h" + + static bool have_guest_debug; + +@@ -872,6 +873,20 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++ /* ++ * For Phytium only, we'll modify registers' value like ID_AA64ISAR0_EL1 ++ * before the virtual machine used for live-migration is started to ensure ++ * that the virtual machine is successfully migrated between different ++ * models of Phytium servers. ++ * Of course, the above will only happen if the CPU model "phytium-v" ++ * is selected during live migration. ++ */ ++ if (is_phytium_cpu()) { ++ ret = modify_arm_vcpu_regs_for_phytium_v(cpu); ++ if (ret < 0) ++ return ret; ++ } ++ + if (cpu_isar_feature(aa64_sve, cpu)) { + ret = kvm_arm_sve_set_vls(cs); + if (ret) { +-- +2.33.0 + diff --git a/SOURCES/0028-support-vm-live-migration-between-phytium-and-kp920.patch b/SOURCES/0028-support-vm-live-migration-between-phytium-and-kp920.patch new file mode 100644 index 0000000..274b860 --- /dev/null +++ b/SOURCES/0028-support-vm-live-migration-between-phytium-and-kp920.patch @@ -0,0 +1,177 @@ +From 91767e7d3cd9d699c2fdbe5f2c4f7b33a4b59779 Mon Sep 17 00:00:00 2001 +From: LiQian +Date: Mon, 14 Jul 2025 17:42:57 +0800 +Subject: [PATCH 3/3] support vm live migration between phytium and kp920 + +Support for migration between phytium and kp920 +when using phytium-v cpu model. + +Support for migration from low to high versions +when using host-passthrough mode. + +Signed-off-by: Peng Mengguang +Signed-off-by: LiQian +--- + hw/intc/arm_gicv3_common.c | 5 +++ + hw/intc/arm_gicv3_kvm.c | 8 +++++ + include/hw/intc/arm_gicv3_common.h | 1 + + target/arm/cpu.h | 1 + + target/arm/helper.c | 50 ++++++++++++++++++++++++++++++ + target/arm/kvm.c | 7 ++--- + 6 files changed, 67 insertions(+), 5 deletions(-) + +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index 9884d2e39b..4a3ca476a0 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -87,6 +87,11 @@ static int gicv3_post_load(void *opaque, int version_id) + gicv3_gicd_no_migration_shift_bug_post_load(s); + + if (c->post_load) { ++ /* load origin value of reg icc_ctrl_el1 when migrate vm */ ++ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ GICv3CPUState *c = &s->cpu[ncpu]; ++ c->icc_ctlr_el1[GICV3_NS] = c->icc_ctlr_el1_origin[GICV3_NS]; ++ } + c->post_load(s); + } + return 0; +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index 5ec5ff9ef6..9226fec70a 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -688,6 +688,8 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) + KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), + &c->icc_ctlr_el1[GICV3_NS], false, &error_abort); + ++ /* save origin value of reg icc_ctrl_el1 for vm migration to use */ ++ c->icc_ctlr_el1_origin[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; + c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; + } + +@@ -706,6 +708,12 @@ static void kvm_arm_gicv3_reset(DeviceState *dev) + } + + kvm_arm_gicv3_put(s); ++ ++ /* save origin value of reg icc_ctrl_el1 */ ++ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ GICv3CPUState *c = &s->cpu[ncpu]; ++ c->icc_ctlr_el1_origin[GICV3_NS] = c->icc_ctlr_el1[GICV3_NS]; ++ } + } + + /* +diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h +index fc38e4b7dc..8217aa123a 100644 +--- a/include/hw/intc/arm_gicv3_common.h ++++ b/include/hw/intc/arm_gicv3_common.h +@@ -178,6 +178,7 @@ struct GICv3CPUState { + /* CPU interface */ + uint64_t icc_sre_el1; + uint64_t icc_ctlr_el1[2]; ++ uint64_t icc_ctlr_el1_origin[2]; + uint64_t icc_pmr_el1; + uint64_t icc_bpr[3]; + uint64_t icc_apr[3][4]; +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index cceb2520f9..080d393297 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -2935,6 +2935,7 @@ typedef struct ARMCPRegUserSpaceInfo { + + void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods); + int modify_arm_vcpu_regs_for_phytium_v(ARMCPU *cpu); ++bool check_compatibility_for_phytium(ARMCPU *cpu); + + /* CPWriteFn that can be used to implement writes-ignored behaviour */ + void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 27384fb8d9..15f4913152 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -140,6 +140,56 @@ int modify_arm_vcpu_regs_for_phytium_v(ARMCPU *cpu) + + return ret; + } ++ ++/* PHYTIUM: check compatibility for live migration on phytium soc. */ ++bool check_compatibility_for_phytium(ARMCPU *cpu) ++{ ++ Object *obj = OBJECT(cpu); ++ ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj); ++ ++ int i; ++ bool ret = true; ++ uint8_t src_impl = 0; ++ uint16_t src_partnum = 0; ++ uint64_t src_midr = 0; ++ ++ if (NULL != acc->info && 0 == strcmp(acc->info->name, "phytium-v")) ++ ret = true; ++ else { ++ for (i = 0; i < cpu->cpreg_array_len; i++) { ++ uint64_t regidx = cpu->cpreg_indexes[i]; ++ if (regidx == ARM64_SYS_REG(3, 0, 0, 0, 0)) { ++ src_midr = cpu->cpreg_values[i]; ++ src_impl = (src_midr >> 24) & 0xff; ++ src_partnum = (src_midr >> 4) & 0x0fff; ++ break; ++ } ++ } ++ ++ if (src_impl == ARM_CPU_IMP_PHYTIUM) { ++ if (is_phytium_cpu()) { ++ if (qemu_read_cpuid_part_number() >= src_partnum) { ++ ret = true; ++ } else { ++ ret = false; ++ } ++ } else if (qemu_read_cpuid_implementor() == 0x48) { ++ if (src_partnum == PHYTIUM_CPU_PART_FTC662 ++ || src_partnum == PHYTIUM_CPU_PART_FTC663) { ++ ret = true; ++ } else { ++ ret = false; ++ } ++ } else { ++ ret = false; ++ } ++ } else { ++ ret = false; ++ } ++ } ++ ++ return ret; ++} + #endif /* TARGET_AARCH64 */ + + static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 1ae4e51055..1103664845 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -32,6 +32,7 @@ + #include "hw/boards.h" + #include "hw/irq.h" + #include "qemu/log.h" ++#include "qemu/aarch64-cpuid.h" + + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +@@ -582,11 +583,7 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) + } + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); + if (ret) { +- /* We might fail for "unknown register" and also for +- * "you tried to set a register which is constant with +- * a different value from what it actually contains". +- */ +- ok = false; ++ ok = check_compatibility_for_phytium(cpu); + } + } + return ok; +-- +2.33.0 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index 1a2b05a..ab804e3 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -83,7 +83,7 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 6.2.0 -Release: 53%{?rcrel}%{?dist} +Release: 54%{?rcrel}%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -885,6 +885,13 @@ Patch361: kvm-nbd-server-Favor-qemu_aio_context-over-iohandler-con.patch Patch362: kvm-iotests-test-NBD-TLS-iothread.patch # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] Patch363: kvm-nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch +# phytium:util: add interfaces to read midr on aarch64 +Patch364: 0026-util-add-interfaces-to-read-midr-on-aarch64.patch +# phytium:cpu: add phytium-v cpu support +Patch365: 0027-cpu-add-phytium-v-cpu-support.patch +# phytium:support vm live migration between phytium and kp920 +Patch366: 0028-support-vm-live-migration-between-phytium-and-kp920.patch + BuildRequires: wget BuildRequires: rpm-build @@ -2054,6 +2061,11 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog +* Tue Jul 15 2025 LiQian - 6.2.0-54.el8 +- Add interfaces that can be used to determine the cpu platform. +- Add phytium-v as a minimal set of phytium server features. This model which is commonly used in live migration. +- Support for migration between phytium and kp920 when using phytium-v cpu model. + * Thu Sep 05 2024 Miroslav Rezanina - 6.2.0-53.el8 - kvm-nbd-server-Favor-qemu_aio_context-over-iohandler-con.patch [RHEL-52611] - kvm-iotests-test-NBD-TLS-iothread.patch [RHEL-52611] -- Gitee