KVM: MIPS/Emulate: Implement 64-bit MMIO emulation
authorJames Hogan <james.hogan@imgtec.com>
Tue, 14 Mar 2017 10:15:16 +0000 (10:15 +0000)
committerJames Hogan <james.hogan@imgtec.com>
Tue, 28 Mar 2017 13:53:45 +0000 (14:53 +0100)
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
arch/mips/kvm/emulate.c

index e0f74ee2aad862637a794b5603b8f5bf8c4f44b9..d75ab8940e1fc562a52e9159ba8e57ef5625b1c2 100644 (file)
@@ -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: