KVM: PPC: Book3S: PR: Enable alternative instruction for SC 1
authorAlexander Graf <agraf@suse.de>
Fri, 14 Dec 2012 22:42:05 +0000 (23:42 +0100)
committerAlexander Graf <agraf@suse.de>
Thu, 10 Jan 2013 12:15:08 +0000 (13:15 +0100)
When running on top of pHyp, the hypercall instruction "sc 1" goes
straight into pHyp without trapping in supervisor mode.

So if we want to support PAPR guest in this configuration we need to
add a second way of accessing PAPR hypercalls, preferably with the
exact same semantics except for the instruction.

So let's overlay an officially reserved instruction and emulate PAPR
hypercalls whenever we hit that one.

Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/book3s_emulate.c
arch/powerpc/kvm/book3s_pr.c

index 572aa75306191272c684a8263a5900cd876352c2..5f5f69abd281be51a9a1b6b7c00f15ef0f332302 100644 (file)
@@ -44,6 +44,7 @@ enum emulation_result {
        EMULATE_DO_DCR,       /* kvm_run filled with DCR request */
        EMULATE_FAIL,         /* can't emulate this instruction */
        EMULATE_AGAIN,        /* something went wrong. go again */
+       EMULATE_DO_PAPR,      /* kvm_run filled with PAPR request */
 };
 
 extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
index d31a716f7f2bc1d06b0a2021a422b1f69e8257e5..c88161bed8dfe5afc48de90a415ce82af5950c0f 100644 (file)
@@ -34,6 +34,8 @@
 #define OP_31_XOP_MTSRIN       242
 #define OP_31_XOP_TLBIEL       274
 #define OP_31_XOP_TLBIE                306
+/* Opcode is officially reserved, reuse it as sc 1 when sc 1 doesn't trap */
+#define OP_31_XOP_FAKE_SC1     308
 #define OP_31_XOP_SLBMTE       402
 #define OP_31_XOP_SLBIE                434
 #define OP_31_XOP_SLBIA                498
@@ -170,6 +172,32 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        vcpu->arch.mmu.tlbie(vcpu, addr, large);
                        break;
                }
+#ifdef CONFIG_KVM_BOOK3S_64_PR
+               case OP_31_XOP_FAKE_SC1:
+               {
+                       /* SC 1 papr hypercalls */
+                       ulong cmd = kvmppc_get_gpr(vcpu, 3);
+                       int i;
+
+                       if ((vcpu->arch.shared->msr & MSR_PR) ||
+                           !vcpu->arch.papr_enabled) {
+                               emulated = EMULATE_FAIL;
+                               break;
+                       }
+
+                       if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE)
+                               break;
+
+                       run->papr_hcall.nr = cmd;
+                       for (i = 0; i < 9; ++i) {
+                               ulong gpr = kvmppc_get_gpr(vcpu, 4 + i);
+                               run->papr_hcall.args[i] = gpr;
+                       }
+
+                       emulated = EMULATE_DO_PAPR;
+                       break;
+               }
+#endif
                case OP_31_XOP_EIOIO:
                        break;
                case OP_31_XOP_SLBMTE:
index 28d38adeca73af0658785a79f94da7a7865ec854..73ed11c41bacfe691f60607c5519b179ae13f3cf 100644 (file)
@@ -760,6 +760,11 @@ program_interrupt:
                        run->exit_reason = KVM_EXIT_MMIO;
                        r = RESUME_HOST_NV;
                        break;
+               case EMULATE_DO_PAPR:
+                       run->exit_reason = KVM_EXIT_PAPR_HCALL;
+                       vcpu->arch.hcall_needed = 1;
+                       r = RESUME_HOST_NV;
+                       break;
                default:
                        BUG();
                }