diff options
author | Christoffer Dall <christoffer.dall@linaro.org> | 2015-07-21 11:18:45 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-07-21 11:18:45 +0100 |
commit | 4b7a6bf402bd064605c287eecadc493ccf2d4897 (patch) | |
tree | 2da235a74cae51293675444895aaa89a507bd1ac /target-arm/kvm32.c | |
parent | a1bc040dabc12039944e22d9529f20d6132400dd (diff) | |
download | qemu-4b7a6bf402bd064605c287eecadc493ccf2d4897.zip qemu-4b7a6bf402bd064605c287eecadc493ccf2d4897.tar.gz qemu-4b7a6bf402bd064605c287eecadc493ccf2d4897.tar.bz2 |
target-arm: kvm: Differentiate registers based on write-back levels
Some registers like the CNTVCT register should only be written to the
kernel as part of machine initialization or on vmload operations, but
never during runtime, as this can potentially make time go backwards or
create inconsistent time observations between VCPUs.
Introduce a list of registers that should not be written back at runtime
and check this list on syncing the register state to the KVM state.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1437046488-10773-1-git-send-email-christoffer.dall@linaro.org
[PMM: tweaked a few comments, added the new argument to the stub
write_list_to_kvmstate() in target-arm/kvm-stub.c]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm/kvm32.c')
-rw-r--r-- | target-arm/kvm32.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c index d7e7d68..421ce0e 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; } |