summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-07-21 12:21:08 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-07-21 12:21:08 +0100
commit774ee4772b6838b78741ea52d4bf26b8922244c5 (patch)
treebb109bb8955284178806f388b14325aedacd4e23
parenta1bc040dabc12039944e22d9529f20d6132400dd (diff)
parent57b73090e041ece40cc619a3c43a6fafcb3dd647 (diff)
downloadqemu-774ee4772b6838b78741ea52d4bf26b8922244c5.tar.gz
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150721' into staging
target-arm queue: * don't sync CNTVCT with kernel all the time (fixes VM time weirdnesses) * fix a warning compiling disas/arm-a64 with -Wextra # gpg: Signature made Tue Jul 21 12:15:33 2015 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20150721: disas/arm-a64: Add missing compiler attribute GCC_FMT_ATTR target-arm: kvm: Differentiate registers based on write-back levels Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--disas/arm-a64.cc4
-rw-r--r--target-arm/kvm-stub.c2
-rw-r--r--target-arm/kvm.c6
-rw-r--r--target-arm/kvm32.c30
-rw-r--r--target-arm/kvm64.c30
-rw-r--r--target-arm/kvm_arm.h12
-rw-r--r--target-arm/machine.c2
7 files changed, 78 insertions, 8 deletions
diff --git a/disas/arm-a64.cc b/disas/arm-a64.cc
index b0803f9cc3..b57256b267 100644
--- a/disas/arm-a64.cc
+++ b/disas/arm-a64.cc
@@ -42,7 +42,7 @@ public:
stream_ = stream;
}
- void SetPrintf(int (*printf_fn)(FILE *, const char *, ...)) {
+ void SetPrintf(fprintf_function printf_fn) {
printf_ = printf_fn;
}
@@ -53,7 +53,7 @@ protected:
}
private:
- int (*printf_)(FILE *, const char *, ...);
+ fprintf_function printf_;
FILE *stream_;
};
diff --git a/target-arm/kvm-stub.c b/target-arm/kvm-stub.c
index cd1849f72c..db2edc2c4c 100644
--- a/target-arm/kvm-stub.c
+++ b/target-arm/kvm-stub.c
@@ -17,7 +17,7 @@ bool write_kvmstate_to_list(ARMCPU *cpu)
abort();
}
-bool write_list_to_kvmstate(ARMCPU *cpu)
+bool write_list_to_kvmstate(ARMCPU *cpu, int level)
{
abort();
}
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 548bfd768d..b278542085 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -409,7 +409,7 @@ bool write_kvmstate_to_list(ARMCPU *cpu)
return ok;
}
-bool write_list_to_kvmstate(ARMCPU *cpu)
+bool write_list_to_kvmstate(ARMCPU *cpu, int level)
{
CPUState *cs = CPU(cpu);
int i;
@@ -421,6 +421,10 @@ bool write_list_to_kvmstate(ARMCPU *cpu)
uint32_t v32;
int ret;
+ if (kvm_arm_cpreg_level(regidx) > level) {
+ continue;
+ }
+
r.id = regidx;
switch (regidx & KVM_REG_SIZE_MASK) {
case KVM_REG_SIZE_U32:
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index d7e7d6877f..421ce0ea0d 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -153,6 +153,34 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
}
}
+typedef struct CPRegStateLevel {
+ uint64_t regidx;
+ int level;
+} CPRegStateLevel;
+
+/* All coprocessor registers not listed in the following table are assumed to
+ * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
+ * often, you must add it to this table with a state of either
+ * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
+ */
+static const CPRegStateLevel non_runtime_cpregs[] = {
+ { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
+};
+
+int kvm_arm_cpreg_level(uint64_t regidx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
+ const CPRegStateLevel *l = &non_runtime_cpregs[i];
+ if (l->regidx == regidx) {
+ return l->level;
+ }
+ }
+
+ return KVM_PUT_RUNTIME_STATE;
+}
+
#define ARM_MPIDR_HWID_BITMASK 0xFFFFFF
#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
@@ -367,7 +395,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
* managed to update the CPUARMState with, and only allowing those
* to be written back up into the kernel).
*/
- if (!write_list_to_kvmstate(cpu)) {
+ if (!write_list_to_kvmstate(cpu, level)) {
return EINVAL;
}
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index ac34f51498..bd60889d12 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -139,6 +139,34 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
}
}
+typedef struct CPRegStateLevel {
+ uint64_t regidx;
+ int level;
+} CPRegStateLevel;
+
+/* All system registers not listed in the following table are assumed to be
+ * of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
+ * often, you must add it to this table with a state of either
+ * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
+ */
+static const CPRegStateLevel non_runtime_cpregs[] = {
+ { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
+};
+
+int kvm_arm_cpreg_level(uint64_t regidx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
+ const CPRegStateLevel *l = &non_runtime_cpregs[i];
+ if (l->regidx == regidx) {
+ return l->level;
+ }
+ }
+
+ return KVM_PUT_RUNTIME_STATE;
+}
+
#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
@@ -280,7 +308,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
return ret;
}
- if (!write_list_to_kvmstate(cpu)) {
+ if (!write_list_to_kvmstate(cpu, level)) {
return EINVAL;
}
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index 5abd5916d1..7912d7433d 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -69,8 +69,18 @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu);
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
/**
+ * kvm_arm_cpreg_level
+ * regidx: KVM register index
+ *
+ * Return the level of this coprocessor/system register. Return value is
+ * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE.
+ */
+int kvm_arm_cpreg_level(uint64_t regidx);
+
+/**
* write_list_to_kvmstate:
* @cpu: ARMCPU
+ * @level: the state level to sync
*
* For each register listed in the ARMCPU cpreg_indexes list, write
* its value from the cpreg_values list into the kernel (via ioctl).
@@ -83,7 +93,7 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
* Note that we do not stop early on failure -- we will attempt
* writing all registers in the list.
*/
-bool write_list_to_kvmstate(ARMCPU *cpu);
+bool write_list_to_kvmstate(ARMCPU *cpu, int level);
/**
* write_kvmstate_to_list:
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 9eb51dfddd..32adfe792e 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -251,7 +251,7 @@ static int cpu_post_load(void *opaque, int version_id)
}
if (kvm_enabled()) {
- if (!write_list_to_kvmstate(cpu)) {
+ if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
return -1;
}
/* Note that it's OK for the TCG side not to know about