Skip to content

Commit

Permalink
arm64: KVM: fix 64bit CP15 VM access for 32bit guests
Browse files Browse the repository at this point in the history
Commit f0a3eaf (ARM64: KVM: fix big endian issue in
access_vm_reg for 32bit guest) changed the way we handle CP15
VM accesses, so that all 64bit accesses are done via vcpu_sys_reg.

This looks like a good idea as it solves indianness issues in an
elegant way, except for one small detail: the register index is
doesn't refer to the same array! We end up corrupting some random
data structure instead.

Fix this by reverting to the original code, except for the introduction
of a vcpu_cp15_64_high macro that deals with the endianness thing.

Tested on Juno with 32bit SMP guests.

Cc: Victor Kamensky <victor.kamensky@linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
  • Loading branch information
Marc Zyngier authored and Christoffer Dall committed Aug 1, 2014
1 parent fb3ec67 commit dedf97e
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 4 deletions.
6 changes: 4 additions & 2 deletions arch/arm64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,11 @@ struct kvm_vcpu_arch {
#define vcpu_cp15(v,r) ((v)->arch.ctxt.copro[(r)])

#ifdef CONFIG_CPU_BIG_ENDIAN
#define vcpu_cp15_64_low(v,r) ((v)->arch.ctxt.copro[((r) + 1)])
#define vcpu_cp15_64_high(v,r) vcpu_cp15((v),(r))
#define vcpu_cp15_64_low(v,r) vcpu_cp15((v),(r) + 1)
#else
#define vcpu_cp15_64_low(v,r) ((v)->arch.ctxt.copro[((r) + 0)])
#define vcpu_cp15_64_high(v,r) vcpu_cp15((v),(r) + 1)
#define vcpu_cp15_64_low(v,r) vcpu_cp15((v),(r))
#endif

struct kvm_vm_stat {
Expand Down
7 changes: 5 additions & 2 deletions arch/arm64/kvm/sys_regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,13 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
BUG_ON(!p->is_write);

val = *vcpu_reg(vcpu, p->Rt);
if (!p->is_aarch32 || !p->is_32bit)
if (!p->is_aarch32) {
vcpu_sys_reg(vcpu, r->reg) = val;
else
} else {
if (!p->is_32bit)
vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
}

return true;
}
Expand Down

0 comments on commit dedf97e

Please sign in to comment.