Signed-off-by: Eric Auger <[email protected]>
---
target/arm/kvm_arm.h | 3 +++
target/arm/kvm-stub.c | 6 +++++
target/arm/kvm.c | 51 +++++++++++++++++++++++++++++++++++++++++
target/arm/trace-events | 1 +
4 files changed, 61 insertions(+)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 2b3474cc36..68e0597ac6 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -250,4 +250,7 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability
*v3);
*/
char *kvm_print_register_name(uint64_t regidx);
+bool kvm_idreg_write_scratch_vcpu(int cpufd, Visitor *v, const char *name,
+ void *opaque, Error **errp);
+
#endif
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
index 88cbe8d85c..264938d2c5 100644
--- a/target/arm/kvm-stub.c
+++ b/target/arm/kvm-stub.c
@@ -119,3 +119,9 @@ char *kvm_print_register_name(uint64_t regidx)
{
g_assert_not_reached();
}
+
+bool kvm_idreg_write_scratch_vcpu(int cpufd, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ g_assert_not_reached();
+}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index fceffee262..e95c6e14ec 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -340,6 +340,57 @@ static ARM64SysRegField *get_field(int i, ARM64SysReg *reg)
return NULL;
}
+bool kvm_idreg_write_scratch_vcpu(int cpufd, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARM64SysRegField *field = (ARM64SysRegField *)opaque;
+ uint64_t mask, old_reg_val, new_reg_val, oldfv, newfv;
+ struct kvm_one_reg reg;
+ int lower = field->shift;
+ int length = field->length;
+ int index = field->index;
+ uint64_t kidx;
+ int ret;
+
+ mask = MAKE_64BIT_MASK(lower, length);
+
+ if (!visit_type_uint64(v, name, &newfv, errp)) {
+ return false;
+ }
+
+ kidx = idregs_sysreg_to_kvm_reg(id_register_sysreg[index]);
+ ret = read_sys_reg64(cpufd, &old_reg_val, kidx);
+ if (ret) {
+ error_setg(errp, "failed to read the scratch vcpu value for field %s
%m",
+ field->name);
+ return false;
+ }
+ oldfv = (old_reg_val & mask) >> lower;
+
+ new_reg_val = old_reg_val & ~mask;
+ new_reg_val |= newfv << lower;
+
+ reg.id = kidx;
+ reg.addr = (uintptr_t)&new_reg_val;
+ ret = ioctl(cpufd, KVM_SET_ONE_REG, ®);
+ if (ret) {
+ error_setg(errp, "failed to apply new value 0x%"PRIx64" for field %s "
+ "(previous is 0x%"PRIx64"): %m", newfv, field->name, oldfv);
+ return false;
+ } else {
+ uint64_t check_val, actualfv;
+
+ ret = read_sys_reg64(cpufd, &check_val, kidx);
+ if (ret) {
+ error_setg(errp, "failed to read the new reg value: %m");
+ return false;
+ }
+ actualfv = (check_val & mask) >> lower;
+ trace_kvm_idreg_write_scratch_vcpu(field->name, oldfv, newfv,
actualfv);
+ }
+ return true;
+}
+
static void set_sysreg_prop(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
diff --git a/target/arm/trace-events b/target/arm/trace-events
index e67730de6b..71a2f5770c 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -20,6 +20,7 @@ get_sysreg_prop(const char *name, uint64_t value) "%s
0x%"PRIx64
set_sysreg_prop(const char *name, uint64_t old, uint64_t mask, uint64_t
field_value, uint64_t new) "%s old reg value=0x%"PRIx64" mask=0x%"PRIx64" new
field value=0x%"PRIx64" new reg value=0x%"PRIx64
nb_sysreg_props(const char *name, int count) "%s: %d SYSREG properties"
unexpected_writable_reserved_field(const char *reg_name, const char
*field_name, int lower, int upper) "Unexpected writable reserved field: %s.%s
[%d,%d], skip it ..."
+kvm_idreg_write_scratch_vcpu(const char *name, uint64_t oldfv, uint64_t newfv,
uint64_t actualfv) "successful dry-run for %s old=0x%"PRIx64" new=0x%"PRIx64"
actual=0x%"PRIx64
# cpu.c
arm_cpu_reset(uint64_t mp_aff) "cpu %" PRIu64
--
2.53.0