[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC v2 07/10] target/arm: Allow ID registers to synchronize to KVM
From: |
Peng Liang |
Subject: |
[RFC v2 07/10] target/arm: Allow ID registers to synchronize to KVM |
Date: |
Thu, 17 Sep 2020 20:14:46 +0800 |
There are 2 steps to synchronize the values of system registers from
CPU state to KVM:
1. write to the values of system registers from CPU state to
(index,value) list by write_cpustate_to_list;
2. write the values in (index,value) list to KVM by
write_list_to_kvmstate;
In step 1, the values of constant system registers are not allowed to
write to (index,value) list. However, a constant system register is
CONSTANT for guest but not for QEMU, which means, QEMU can set/modify
the value of constant system registers that is different from phsical
registers when startup. But if KVM is enabled, guest can not read the
values of the system registers which QEMU set unless they can be written
to (index,value) list. And why not try to write to KVM if kvm_sync is
true?
At the moment we call write_cpustate_to_list, all ID registers are
contant, including ID_PFR1_EL1 and ID_AA64PFR0_EL1 because GIC has been
initialized. Hence, let's give all ID registers a chance to write to
KVM. If the write is successful, then write to (index,value) list.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/kvm_arm.h | 3 +++
target/arm/helper.c | 46 +++++++++++++++++++++++++++++++++-----------
target/arm/kvm.c | 38 ++++++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 33b3f107b47d..cf1c9c9cdb4c 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -479,4 +479,7 @@ static inline const char *its_class_name(void)
}
}
+int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target);
+int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source);
+
#endif
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 26fef7424904..e489d744f15a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -34,6 +34,7 @@
#include "arm_ldst.h"
#include "exec/cpu_ldst.h"
#endif
+#include "kvm_arm.h"
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
@@ -353,6 +354,16 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
return true;
}
+static inline bool is_id_register(const ARMCPRegInfo *ri)
+{
+ /*
+ * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2),
+ * where 1<=crm<8, 0<=op2<8.
+ */
+ return ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 &&
+ ri->crm > 0 && ri->crm < 8;
+}
+
bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
{
/* Write the coprocessor state from cpu->env to the (index,value) list. */
@@ -369,30 +380,43 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
ok = false;
continue;
}
- if (ri->type & ARM_CP_NO_RAW) {
+ /* Let's give ID registers a chance to synchronize to kvm. */
+ if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync && is_id_register(ri))) {
continue;
}
newval = read_raw_cp_reg(&cpu->env, ri);
if (kvm_sync) {
- /*
- * Only sync if the previous list->cpustate sync succeeded.
- * Rather than tracking the success/failure state for every
- * item in the list, we just recheck "does the raw write we must
- * have made in write_list_to_cpustate() read back OK" here.
- */
- uint64_t oldval = cpu->cpreg_values[i];
+ /* Only sync if we can sync to KVM successfully. */
+ uint64_t oldval;
+ uint64_t kvmval;
+ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) {
+ continue;
+ }
if (oldval == newval) {
continue;
}
- write_raw_cp_reg(&cpu->env, ri, oldval);
- if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
+ if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) {
+ if (is_id_register(ri)) {
+ ok = false;
+ error_report("Cannot set ID regsiter %s: %s", ri->name,
+ strerror(errno));
+ }
+ continue;
+ }
+ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) ||
+ kvmval != newval) {
+ if (is_id_register(ri)) {
+ ok = false;
+ error_report("Setting ID register %s doesn't effect",
+ ri->name);
+ }
continue;
}
- write_raw_cp_reg(&cpu->env, ri, newval);
+ kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval);
}
cpu->cpreg_values[i] = newval;
}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 2eae73315d6e..5b5cde5e821e 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -490,6 +490,44 @@ out:
return ret;
}
+int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target)
+{
+ uint32_t v32;
+ int ret;
+
+ switch (regidx & KVM_REG_SIZE_MASK) {
+ case KVM_REG_SIZE_U32:
+ ret = kvm_get_one_reg(CPU(cpu), regidx, &v32);
+ if (ret == 0) {
+ *target = v32;
+ }
+ return ret;
+ case KVM_REG_SIZE_U64:
+ return kvm_get_one_reg(CPU(cpu), regidx, target);
+ default:
+ return -1;
+ }
+}
+
+int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source)
+{
+ uint32_t v32;
+
+ switch (regidx & KVM_REG_SIZE_MASK) {
+ case KVM_REG_SIZE_U32:
+ v32 = *source;
+ if (v32 != *source) {
+ error_report("the value of source is too large");
+ return -1;
+ }
+ return kvm_set_one_reg(CPU(cpu), regidx, &v32);
+ case KVM_REG_SIZE_U64:
+ return kvm_set_one_reg(CPU(cpu), regidx, source);
+ default:
+ return -1;
+ }
+}
+
bool write_kvmstate_to_list(ARMCPU *cpu)
{
CPUState *cs = CPU(cpu);
--
2.26.2
- [RFC v2 00/10] Support disable/enable CPU features for AArch64, Peng Liang, 2020/09/17
- [RFC v2 01/10] linux-header: Introduce KVM_CAP_ARM_CPU_FEATURE, Peng Liang, 2020/09/17
- [RFC v2 03/10] target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest, Peng Liang, 2020/09/17
- [RFC v2 02/10] target/arm: Update ID fields, Peng Liang, 2020/09/17
- [RFC v2 04/10] target/arm: convert isar regs to array, Peng Liang, 2020/09/17
- [RFC v2 05/10] target/arm: Introduce kvm_arm_cpu_feature_supported, Peng Liang, 2020/09/17
- [RFC v2 07/10] target/arm: Allow ID registers to synchronize to KVM,
Peng Liang <=
- [RFC v2 08/10] target/arm: Introduce user_mask to indicate whether the feature is set explicitly, Peng Liang, 2020/09/17
- [RFC v2 10/10] target/arm: Add CPU features to query-cpu-model-expansion, Peng Liang, 2020/09/17
- [RFC v2 06/10] target/arm: register CPU features for property, Peng Liang, 2020/09/17
- [RFC v2 09/10] target/arm: introduce CPU feature dependency mechanism, Peng Liang, 2020/09/17