Introduce kvm_arm_override_idreg_field() helper that allows to read an ID register value from a vcpu fd, override a given field value and reinject the new register value in the guest vcpu.
The helper is not used yet, hence the G_GNUC_UNUSED marker. It will be used in subsequent patch to apply a new field value set through SYSREG property. Signed-off-by: Eric Auger <[email protected]> --- target/arm/kvm.c | 48 ++++++++++++++++++++++++++++++++++++++++- target/arm/trace-events | 1 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 6c15d8522f..c6c9ea03a5 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -1247,6 +1247,50 @@ bool kvm_arm_cpu_post_load(ARMCPU *cpu) return true; } +static int G_GNUC_UNUSED +kvm_arm_override_idreg_field(int fd, ARM64SysRegField *field, + uint64_t newfv, Error **errp) +{ + uint64_t current, currentfv, value; + struct kvm_one_reg kvm_reg; + int index = field->index; + int length = field->length; + int lower = field->shift; + ARM64SysReg *reg; + uint64_t kvm_idx; + int ret; + + reg = &arm64_id_regs[index]; + + kvm_idx = idregs_sysreg_to_kvm_reg(id_register_sysreg[index]); + + ret = read_sys_reg64(fd, ¤t, kvm_idx); + if (ret) { + error_setg(errp, "failed to read %s current value", reg->name); + return ret; + } + currentfv = extract64(current, lower, length); + + if (currentfv != newfv) { + value = deposit64(current, lower, length, newfv); + kvm_reg.id = kvm_idx; + kvm_reg.addr = (uintptr_t)&value; + + ret = ioctl(fd, KVM_SET_ONE_REG, &kvm_reg); + if (ret) { + error_setg(errp, + "ID register field %s.%s: fail to apply new value=0x%" + PRIx64" (current is 0x%"PRIx64"): %m", + reg->name, field->name, newfv, currentfv); + + return ret; + } + } + trace_kvm_arm_override_idreg_field(reg->name, field->name, + currentfv, newfv); + return 0; +} + void kvm_arm_reset_vcpu(ARMCPU *cpu) { int ret; @@ -1259,6 +1303,7 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu) fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); abort(); } + if (!write_kvmstate_to_list(cpu)) { fprintf(stderr, "write_kvmstate_to_list failed\n"); abort(); @@ -2204,7 +2249,8 @@ int kvm_arch_init_vcpu(CPUState *cs, Error **errp) return ret; } SET_IDREG(&cpu->isar, MPIDR, mpidr); - cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK; + + cpu->mp_affinity = GET_IDREG(&cpu->isar, MPIDR) & ARM64_AFFINITY_MASK; return kvm_arm_init_cpreg_list(cpu, errp); } diff --git a/target/arm/trace-events b/target/arm/trace-events index ddc79eb666..81564f1d96 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -14,6 +14,7 @@ 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 get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host value for %s is 0x%"PRIx64 +kvm_arm_override_idreg_field(const char *reg_name, const char *field_name, uint64_t currentfv, uint64_t newfv) "%s.%s current=0x%"PRIx64" new=0x%"PRIx64 # cpu.c arm_cpu_reset(uint64_t mp_aff) "cpu %" PRIu64 -- 2.53.0
