aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2014-08-01 07:00:36 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2014-08-01 08:05:06 -0400
commitdedf97e8ff2c7513b1370e36b56e08b6bd0f0290 (patch)
tree87dd96b3da3d826dc06f5d40a4eeb3445af9d18d
parentfb3ec67942e92e5713e05b7691b277d0a0c0575d (diff)
arm64: KVM: fix 64bit CP15 VM access for 32bit guests
Commit f0a3eaff71b8 (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>
-rw-r--r--arch/arm64/include/asm/kvm_host.h6
-rw-r--r--arch/arm64/kvm/sys_regs.c7
2 files changed, 9 insertions, 4 deletions
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 79812be4f25f..e10c45a578e3 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -149,9 +149,11 @@ struct kvm_vcpu_arch {
149#define vcpu_cp15(v,r) ((v)->arch.ctxt.copro[(r)]) 149#define vcpu_cp15(v,r) ((v)->arch.ctxt.copro[(r)])
150 150
151#ifdef CONFIG_CPU_BIG_ENDIAN 151#ifdef CONFIG_CPU_BIG_ENDIAN
152#define vcpu_cp15_64_low(v,r) ((v)->arch.ctxt.copro[((r) + 1)]) 152#define vcpu_cp15_64_high(v,r) vcpu_cp15((v),(r))
153#define vcpu_cp15_64_low(v,r) vcpu_cp15((v),(r) + 1)
153#else 154#else
154#define vcpu_cp15_64_low(v,r) ((v)->arch.ctxt.copro[((r) + 0)]) 155#define vcpu_cp15_64_high(v,r) vcpu_cp15((v),(r) + 1)
156#define vcpu_cp15_64_low(v,r) vcpu_cp15((v),(r))
155#endif 157#endif
156 158
157struct kvm_vm_stat { 159struct kvm_vm_stat {
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index a4fd5267c65b..5805e7c4a4dd 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -135,10 +135,13 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
135 BUG_ON(!p->is_write); 135 BUG_ON(!p->is_write);
136 136
137 val = *vcpu_reg(vcpu, p->Rt); 137 val = *vcpu_reg(vcpu, p->Rt);
138 if (!p->is_aarch32 || !p->is_32bit) 138 if (!p->is_aarch32) {
139 vcpu_sys_reg(vcpu, r->reg) = val; 139 vcpu_sys_reg(vcpu, r->reg) = val;
140 else 140 } else {
141 if (!p->is_32bit)
142 vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
141 vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL; 143 vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
144 }
142 145
143 return true; 146 return true;
144} 147}