diff options
author | Pavel Fedin <p.fedin@samsung.com> | 2015-12-04 15:03:11 +0300 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2015-12-04 16:29:37 +0000 |
commit | bc45a516fa90b43b1898758d8b53b74c24b954e4 (patch) | |
tree | ac99c251f2a2b292166fec8227f2438fb830150c /arch/arm/kvm | |
parent | fbb4574ce9a37e15a9872860bf202f2be5bdf6c4 (diff) | |
download | op-kernel-dev-bc45a516fa90b43b1898758d8b53b74c24b954e4.zip op-kernel-dev-bc45a516fa90b43b1898758d8b53b74c24b954e4.tar.gz |
arm64: KVM: Correctly handle zero register during MMIO
On ARM64 register index of 31 corresponds to both zero register and SP.
However, all memory access instructions, use ZR as transfer register. SP
is used only as a base register in indirect memory addressing, or by
register-register arithmetics, which cannot be trapped here.
Correct emulation is achieved by introducing new register accessor
functions, which can do special handling for reg_num == 31. These new
accessors intentionally do not rely on old vcpu_reg() on ARM64, because
it is to be removed. Since the affected code is shared by both ARM
flavours, implementations of these accessors are also added to ARM32 code.
This patch fixes setting MMIO register to a random value (actually SP)
instead of zero by something like:
*((volatile int *)reg) = 0;
compilers tend to generate "str wzr, [xx]" here
[Marc: Fixed 32bit splat]
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm/kvm')
-rw-r--r-- | arch/arm/kvm/mmio.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c index 974b1c6..3a10c9f 100644 --- a/arch/arm/kvm/mmio.c +++ b/arch/arm/kvm/mmio.c @@ -115,7 +115,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, data); data = vcpu_data_host_to_guest(vcpu, data, len); - *vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt) = data; + vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data); } return 0; @@ -186,7 +186,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, rt = vcpu->arch.mmio_decode.rt; if (is_write) { - data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt), len); + data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt), + len); trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); mmio_write_buf(data_buf, len, data); |