
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/qemu/issues/IBSJV9 ------------------------------------------------------------------------ MIDR/AIDR/REVIDR are treated as invariant registers by ARM64 KVM and hence not possible to write a value that differs from host CPU. This will break migration if they are different. Ignore invariant register difference and keep the host value for Kunpeng 920 for now. Find a better way to do this. Also investigate KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 difference. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- target/arm/cpu.h | 1 + target/arm/kunpeng920-regs.c | 5 +++++ target/arm/kvm.c | 15 +++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 6622256bdd..db59ce8644 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1123,6 +1123,7 @@ struct ArchCPU { uint64_t gt_cntfrq_hz; uint64_t *writable_masks; + bool ignore_invariant_reg; }; typedef struct ARMCPUInfo { diff --git a/target/arm/kunpeng920-regs.c b/target/arm/kunpeng920-regs.c index 8a764a2011..a424a14d28 100644 --- a/target/arm/kunpeng920-regs.c +++ b/target/arm/kunpeng920-regs.c @@ -38,5 +38,10 @@ int kunpeng920_update_registers(ARMCPU *cpu) cpu->isar.id_aa64zfr0 = 0x100000100000; cpu->ctr = 0xb4448004; + /* + * MIDR/REVIDR/AIDR are invariant registers and not writable. + * Ignore any differences between HIP09、HIP10 and HIP12 for now. + */ + cpu->ignore_invariant_reg = true; return 0; } diff --git a/target/arm/kvm.c b/target/arm/kvm.c index d98c3d1bf5..eb72f44eaa 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -602,6 +602,18 @@ bool write_kvmstate_to_list(ARMCPU *cpu) return ok; } +static bool is_invariant_reg(uint64_t regidx) +{ + /* We need a better way to handle this */ + if ((regidx == ARM64_SYS_REG(3, 0, 0, 0, 0)) || /*MIDR*/ + (regidx == ARM64_SYS_REG(3, 1, 0, 0, 7)) || /*AIDR*/ + (regidx == KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3)) { + return true; + } + + return false; +} + bool write_list_to_kvmstate(ARMCPU *cpu, int level) { CPUState *cs = CPU(cpu); @@ -628,6 +640,9 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) break; case KVM_REG_SIZE_U64: ret = kvm_set_one_reg(cs, regidx, cpu->cpreg_values + i); + if (ret && cpu->ignore_invariant_reg && is_invariant_reg(regidx)) { + ret = kvm_get_one_reg(cs, regidx, cpu->cpreg_values + i); + } break; default: g_assert_not_reached(); -- 2.33.0