From fbc74481fa99b610c9829de654a22a3b33dbb609 Mon Sep 17 00:00:00 2001 From: Jiakun Shuai Date: Fri, 28 Jun 2024 17:29:54 +0800 Subject: [PATCH] QEMU update to version 6.2.0-94: - support-vm-live-migration-between-phytium-soc-qemu6.2.0-new.patch Signed-off-by: Jiakun Shuai --- qemu.spec | 6 +- ...ive-migration-between-phytium-soc-oe.patch | 546 ++++++++++++++++++ 2 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 support-vm-live-migration-between-phytium-soc-oe.patch diff --git a/qemu.spec b/qemu.spec index 127617a8..f4074341 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 93 +Release: 94 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -968,6 +968,7 @@ Patch0953: Add-support-for-the-virtcca-cvm-feature.patch Patch0954: hw-ide-reset-cancel-async-DMA-operation-before-reset.patch Patch0955: tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch Patch0956: cvm-bug-fix-for-macro-isolation.patch +Patch0957: support-vm-live-migration-between-phytium-soc-oe.patch BuildRequires: flex BuildRequires: gcc @@ -1566,6 +1567,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Jun 28 2024 - 10:6.2.0-94 +- support-vm-live-migration-between-phytium-soc-oe.patch + * Sat Jun 15 2024 - 10:6.2.0-93 - cvm: bug-fix for macro isolation - tests/qtest: ahci-test: add test exposing reset issue with pending callback (Fix CVE-2023-5088) diff --git a/support-vm-live-migration-between-phytium-soc-oe.patch b/support-vm-live-migration-between-phytium-soc-oe.patch new file mode 100644 index 00000000..c382998e --- /dev/null +++ b/support-vm-live-migration-between-phytium-soc-oe.patch @@ -0,0 +1,546 @@ +From fa467fe83cb299feef2cc60f71bfa0fdcf3f874f Mon Sep 17 00:00:00 2001 +From: pengmengguang +Date: Sat, 29 Jun 2024 12:05:08 -0400 +Subject: [PATCH] support vm live migration between phytium soc + +--- + hw/arm/virt.c | 1 + + hw/intc/arm_gicv3_common.c | 14 +++- + hw/intc/arm_gicv3_kvm.c | 15 +++- + include/hw/intc/arm_gicv3_common.h | 1 + + include/qemu/aarch64-cpuid.h | 46 +++++++++++ + target/arm/cpu.h | 3 + + target/arm/cpu64.c | 36 +++++++++ + target/arm/helper.c | 123 +++++++++++++++++++++++++++++ + target/arm/kvm.c | 12 +-- + target/arm/kvm64.c | 15 ++++ + util/aarch64-cpuid.c | 76 ++++++++++++++++++ + util/meson.build | 1 + + 12 files changed, 333 insertions(+), 10 deletions(-) + create mode 100644 include/qemu/aarch64-cpuid.h + create mode 100644 util/aarch64-cpuid.c + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index f20775f44..807c28924 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -213,6 +213,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 MemoryRegion *secure_sysmem; +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index a4976b2ba..7e9850c70 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -33,6 +33,7 @@ + #include "hw/arm/linux-boot-if.h" + #include "hw/boards.h" + #include "sysemu/kvm.h" ++#include "qemu/aarch64-cpuid.h" + + + static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs) +@@ -89,9 +90,16 @@ static int gicv3_post_load(void *opaque, int version_id) + gicv3_gicd_no_migration_shift_bug_post_load(s); + + if (c->post_load) { +- c->post_load(s); +- } +- return 0; ++ if (is_phytium_cpu()) { ++ /* 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; + } + + static bool virt_state_needed(void *opaque) +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index 2e2b08e31..a6e89de3c 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -31,6 +31,7 @@ + #include "vgic_common.h" + #include "migration/blocker.h" + #include "qom/object.h" ++#include "qemu/aarch64-cpuid.h" + + #ifdef DEBUG_GICV3_KVM + #define DPRINTF(fmt, ...) \ +@@ -713,7 +714,11 @@ 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); + +- c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; ++ /* save origin value of reg icc_ctrl_el1 for vm migration to use */ ++ if (is_phytium_cpu()) ++ c->icc_ctlr_el1_origin[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; ++ else ++ c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; + } + + static void kvm_arm_gicv3_reset(DeviceState *dev) +@@ -731,6 +736,14 @@ static void kvm_arm_gicv3_reset(DeviceState *dev) + } + + kvm_arm_gicv3_put(s); ++ ++ /* save origin value of reg icc_ctrl_el1 */ ++ if (is_phytium_cpu()) { ++ 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 c208a191f..0ae49ed2b 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/include/qemu/aarch64-cpuid.h b/include/qemu/aarch64-cpuid.h +new file mode 100644 +index 000000000..87156a2d5 +--- /dev/null ++++ b/include/qemu/aarch64-cpuid.h +@@ -0,0 +1,46 @@ ++#ifndef QEMU_AARCH64_CPUID_H ++#define QEMU_AARCH64_CPUID_H ++ ++#if defined(__aarch64__) ++#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 ++ ++#endif +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index eb804dffa..b69cc64cb 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -2943,6 +2943,9 @@ typedef struct ARMCPRegUserSpaceInfo { + + #define REGUSERINFO_SENTINEL { .name = NULL } + ++int modify_arm_vcpu_regs_for_phytium_v(ARMCPU *cpu); ++bool check_compatibility_for_phytium(ARMCPU *cpu); ++ + void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods); + + /* CPWriteFn that can be used to implement writes-ignored behaviour */ +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 3ec788fc2..fe7025ca6 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -957,6 +957,41 @@ 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 }, +@@ -964,6 +999,7 @@ static const ARMCPUInfo aarch64_cpus[] = { + { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn}, + { .name = "FT-2000+", .initfn = aarch64_max_ft2000plus_initfn }, + { .name = "Tengyun-S2500", .initfn = aarch64_max_tengyun_s2500_initfn }, ++ { .name = "phytium-v", .initfn = aarch64_phytium_v_initfn }, + { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, + { .name = "max", .initfn = aarch64_max_initfn }, + }; +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 1854c6586..e4abf82de 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" +@@ -8887,6 +8888,128 @@ void define_arm_cp_regs_with_opaque(ARMCPU *cpu, + } + } + ++#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[] = { ++ { .name = "ID_PFR0_EL1", .reg = SYS_ID_PFR0_EL1, .value = 0 }, ++ { .name = "ID_PFR1_EL1", .reg = SYS_ID_PFR1_EL1, .value = 0 }, ++ { .name = "ID_PFR2_EL1", .reg = SYS_ID_PFR2_EL1, .value = 0 }, ++ { .name = "ID_DFR0_EL1", .reg = SYS_ID_DFR0_EL1, .value = 0 }, ++ { .name = "ID_MMFR0_EL1", .reg = SYS_ID_MMFR0_EL1, .value = 0 }, ++ { .name = "ID_MMFR1_EL1", .reg = SYS_ID_MMFR1_EL1, .value = 0 }, ++ { .name = "ID_MMFR2_EL1", .reg = SYS_ID_MMFR2_EL1, .value = 0 }, ++ { .name = "ID_MMFR3_EL1", .reg = SYS_ID_MMFR3_EL1, .value = 0 }, ++ { .name = "ID_MMFR4_EL1", .reg = SYS_ID_MMFR4_EL1, .value = 0 }, ++ { .name = "ID_ISAR0_EL1", .reg = SYS_ID_ISAR0_EL1, .value = 0 }, ++ { .name = "ID_ISAR1_EL1", .reg = SYS_ID_ISAR1_EL1, .value = 0 }, ++ { .name = "ID_ISAR2_EL1", .reg = SYS_ID_ISAR2_EL1, .value = 0 }, ++ { .name = "ID_ISAR3_EL1", .reg = SYS_ID_ISAR3_EL1, .value = 0 }, ++ { .name = "ID_ISAR4_EL1", .reg = SYS_ID_ISAR4_EL1, .value = 0 }, ++ { .name = "ID_ISAR5_EL1", .reg = SYS_ID_ISAR5_EL1, .value = 0 }, ++ { .name = "ID_ISAR6_EL1", .reg = SYS_ID_ISAR6_EL1, .value = 0 }, ++ { .name = "MVFR0_EL1", .reg = SYS_MVFR0_EL1, .value = 0 }, ++ { .name = "MVFR1_EL1", .reg = SYS_MVFR1_EL1, .value = 0 }, ++ { .name = "MVFR2_EL1", .reg = SYS_MVFR2_EL1, .value = 0 }, ++ { .name = "ID_AA64PFR0_EL1", .reg = SYS_ID_AA64PFR0_EL1, .value = 0x01001111 }, ++ { .name = "ID_AA64PFR1_EL1", .reg = SYS_ID_AA64PFR1_EL1, .value = 0 }, ++ { .name = "ID_AA64DFR0_EL1", .reg = SYS_ID_AA64DFR0_EL1, .value = 0x10305106 }, ++ { .name = "ID_AA64ISAR0_EL1", .reg = SYS_ID_AA64ISAR0_EL1, .value = 0x10000 }, ++ { .name = "ID_AA64ISAR1_EL1", .reg = SYS_ID_AA64ISAR1_EL1, .value = 0 }, ++ { .name = "ID_AA64MMFR0_EL1", .reg = SYS_ID_AA64MMFR0_EL1, .value = 0x1124 }, ++ { .name = "ID_AA64MMFR1_EL1", .reg = SYS_ID_AA64MMFR1_EL1, .value = 0 }, ++ { .name = "ID_AA64MMFR2_EL1", .reg = SYS_ID_AA64MMFR2_EL1, .value = 0 }, ++}; ++ ++/* PHYTIUM : modify sys_regs for live-migration. */ ++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 < sizeof(sys_regs_info) / sizeof(sys_regs_info[0]); i++) { ++ val = sys_regs_info[i].value; ++ ret = kvm_set_one_reg(cs, sys_regs_info[i].reg, &val); ++ if (ret) ++ break; ++ } ++ } ++ ++ 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 (qemu_read_cpuid_part_number() >= src_partnum) ++ ret = true; ++ else ++ ret = false; ++ } else ++ ret = false; ++ } ++ ++ return ret; ++} ++ + /* + * Modify ARMCPRegInfo for access from userspace. + * +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index f62d9ece3..0048d8d63 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -34,6 +34,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 +@@ -561,7 +562,7 @@ bool write_kvmstate_to_list(ARMCPU *cpu) + bool ok = true; + + for (i = 0; i < cpu->cpreg_array_len; i++) { +- struct kvm_one_reg r; ++ struct kvm_one_reg r; + uint64_t regidx = cpu->cpreg_indexes[i]; + uint32_t v32; + int ret; +@@ -622,11 +623,10 @@ 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; ++ if (is_phytium_cpu()) ++ ok = check_compatibility_for_phytium(cpu); ++ else ++ ok = false; + } + } + return ok; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 38d519846..38bcf2300 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; + +@@ -896,6 +897,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) { +diff --git a/util/aarch64-cpuid.c b/util/aarch64-cpuid.c +new file mode 100644 +index 000000000..4a8d2ad52 +--- /dev/null ++++ b/util/aarch64-cpuid.c +@@ -0,0 +1,76 @@ ++/* ++ * 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 05b593055..6e7deccc5 100644 +--- a/util/meson.build ++++ b/util/meson.build +@@ -48,6 +48,7 @@ util_ss.add(files('transactions.c')) + 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('aarch64-cpuid.c')) + + if have_user + util_ss.add(files('selfmap.c')) +-- +2.39.3 + -- Gitee