diff options
author | James Hogan <james.hogan@imgtec.com> | 2017-03-14 10:15:16 +0000 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2017-03-28 14:53:45 +0100 |
commit | 59d7814ab26f925f209d532ae40f797f20359cec (patch) | |
tree | c62984e697bc9e870a7fa7c617c5f6d2ed0576d8 /arch | |
parent | 8b48d5b75dc4cbae8cfe83648f9e4e10cb407dce (diff) |
KVM: MIPS/Emulate: Implement 64-bit MMIO emulation
Implement additional MMIO emulation for MIPS64, including 64-bit
loads/stores, and 32-bit unsigned loads. These are only exposed on
64-bit VZ hosts.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kvm/emulate.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index e0f74ee2aad8..d75ab8940e1f 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1499,6 +1499,17 @@ enum emulation_result kvm_mips_emulate_store(union mips_instruction inst, goto out_fail; switch (inst.i_format.opcode) { +#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_MIPS_VZ) + case sd_op: + run->mmio.len = 8; + *(u64 *)data = vcpu->arch.gprs[rt]; + + kvm_debug("[%#lx] OP_SD: eaddr: %#lx, gpr: %#lx, data: %#llx\n", + vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr, + vcpu->arch.gprs[rt], *(u64 *)data); + break; +#endif + case sw_op: run->mmio.len = 4; *(u32 *)data = vcpu->arch.gprs[rt]; @@ -1575,6 +1586,15 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, vcpu->mmio_needed = 2; /* signed */ switch (op) { +#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_MIPS_VZ) + case ld_op: + run->mmio.len = 8; + break; + + case lwu_op: + vcpu->mmio_needed = 1; /* unsigned */ + /* fall through */ +#endif case lw_op: run->mmio.len = 4; break; @@ -2421,8 +2441,15 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, vcpu->arch.pc = vcpu->arch.io_pc; switch (run->mmio.len) { + case 8: + *gpr = *(s64 *)run->mmio.data; + break; + case 4: - *gpr = *(s32 *) run->mmio.data; + if (vcpu->mmio_needed == 2) + *gpr = *(s32 *)run->mmio.data; + else + *gpr = *(u32 *)run->mmio.data; break; case 2: |