
From: Eric Auger <eric.auger@redhat.com> We want to give a chance to override the value of host ID regs. In a previous patch we made sure all their values could be fetched through kvm_get_one_reg() calls before their modification. After their potential modification we need to make sure we write back the values through kvm_set_one_reg() calls. Make sure the cpreg_list is modified with updated values and transfer those values back to kvm. Signed-off-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com> --- target/arm/kvm.c | 34 ++++++++++++++++++++++++++++++++++ target/arm/kvm64.c | 13 +++++++++++-- target/arm/kvm_arm.h | 6 ++++++ target/arm/trace-events | 1 + 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index e97bdcb7e1..bb9225cb2f 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -23,6 +23,7 @@ #include "sysemu/kvm_int.h" #include "kvm_arm.h" #include "cpu.h" +#include "cpu-custom.h" #include "cpu-sysregs.h" #include "trace.h" #include "internals.h" @@ -794,6 +795,39 @@ static void kvm_arm_configure_vcpu_regs(ARMCPU *cpu) kvm_arm_configure_pmcr(cpu); } +void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) +{ + if (!cpu->writable_map) { + return; + } + for (int i = 0; i < NR_ID_REGS; i++) { + uint64_t writable_mask = cpu->writable_map->regs[i]; + uint64_t *cpreg; + + if (writable_mask) { + uint64_t previous, new; + int idx = kvm_idx_to_idregs_idx(i); + ARM64SysReg *sysregdesc; + uint32_t sysreg; + + if (idx == -1) { + /* sysreg writable, but we don't know it */ + continue; + } + sysregdesc = &arm64_id_regs[idx]; + sysreg = sysregdesc->sysreg; + cpreg = kvm_arm_get_cpreg_ptr(cpu, idregs_sysreg_to_kvm_reg(sysreg)); + previous = *cpreg; + new = cpu->isar.idregs[idx]; + if (previous != new) { + *cpreg = new; + trace_kvm_arm_writable_idregs_to_cpreg_list(sysregdesc->name, + previous, new); + } + } + } +} + void kvm_arm_reset_vcpu(ARMCPU *cpu) { int ret; diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index da9352b14d..be9233f936 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -470,7 +470,7 @@ bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, if (exhaustive) { err |= get_host_cpu_idregs(cpu, fd, ahcf); } - + /* * DBGDIDR is a bit complicated because the kernel doesn't * provide an accessor for it in 64-bit mode, which is what this @@ -757,7 +757,16 @@ int kvm_arch_init_vcpu(CPUState *cs) /* Check whether user space can specify guest syndrome value */ kvm_arm_init_serror_injection(cs); - return kvm_arm_init_cpreg_list(cpu); + ret = kvm_arm_init_cpreg_list(cpu); + if (ret) { + return ret; + } + /* overwrite writable ID regs with their updated property values */ + kvm_arm_writable_idregs_to_cpreg_list(cpu); + + write_list_to_kvmstate(cpu, 3); + + return 0; } int kvm_arch_destroy_vcpu(CPUState *cs) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index b82e04e25b..e7126d1844 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -471,6 +471,8 @@ Object *kvm_arm_rme_get_measurement_log(void); int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap); +void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu); + #else /* @@ -516,6 +518,10 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) return -ENOSYS; } +void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) +{ + g_assert_not_reached(); +} /* * These functions should never actually be called without KVM support. */ diff --git a/target/arm/trace-events b/target/arm/trace-events index 49162b87b2..fe8721d66a 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -15,3 +15,4 @@ get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host value f # kvm.c kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 +kvm_arm_writable_idregs_to_cpreg_list(const char *name, uint64_t previous, uint64_t new) "%s overwrite default 0x%"PRIx64" with 0x%"PRIx64 -- 2.33.0