KVM: PPC: Book3S PR: Add emulation for slbfee. instruction
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 4 Feb 2019 08:06:18 +0000 (19:06 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 19 Feb 2019 03:25:52 +0000 (14:25 +1100)
Recent kernels, since commit e15a4fea4dee ("powerpc/64s/hash: Add
some SLB debugging tests", 2018-10-03) use the slbfee. instruction,
which PR KVM currently does not have code to emulate.  Consequently
recent kernels fail to boot under PR KVM.  This adds emulation of
slbfee., enabling these kernels to boot successfully.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_32_mmu.c
arch/powerpc/kvm/book3s_64_mmu.c
arch/powerpc/kvm/book3s_emulate.c

index 0f98f00da2ea3b7027e29efbf0bf3c4b8a7116be..091430339db11e4e061c833f5dd4d3cb1c091fbf 100644 (file)
@@ -377,6 +377,7 @@ struct kvmppc_mmu {
        void (*slbmte)(struct kvm_vcpu *vcpu, u64 rb, u64 rs);
        u64  (*slbmfee)(struct kvm_vcpu *vcpu, u64 slb_nr);
        u64  (*slbmfev)(struct kvm_vcpu *vcpu, u64 slb_nr);
+       int  (*slbfee)(struct kvm_vcpu *vcpu, gva_t eaddr, ulong *ret_slb);
        void (*slbie)(struct kvm_vcpu *vcpu, u64 slb_nr);
        void (*slbia)(struct kvm_vcpu *vcpu);
        /* book3s */
index 612169988a3d8a15262665e03d3cc9cfddb4a87e..6f789f674048a4c2a534ad338f3162e33c4068cb 100644 (file)
@@ -425,6 +425,7 @@ void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu)
        mmu->slbmte = NULL;
        mmu->slbmfee = NULL;
        mmu->slbmfev = NULL;
+       mmu->slbfee = NULL;
        mmu->slbie = NULL;
        mmu->slbia = NULL;
 }
index c92dd25bed237bcd9ac488401c80ed4b3d304aed..d4b967f0e8d4bd1de83f40a40b11c9b02ef97d89 100644 (file)
@@ -435,6 +435,19 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
        kvmppc_mmu_map_segment(vcpu, esid << SID_SHIFT);
 }
 
+static int kvmppc_mmu_book3s_64_slbfee(struct kvm_vcpu *vcpu, gva_t eaddr,
+                                      ulong *ret_slb)
+{
+       struct kvmppc_slb *slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu, eaddr);
+
+       if (slbe) {
+               *ret_slb = slbe->origv;
+               return 0;
+       }
+       *ret_slb = 0;
+       return -ENOENT;
+}
+
 static u64 kvmppc_mmu_book3s_64_slbmfee(struct kvm_vcpu *vcpu, u64 slb_nr)
 {
        struct kvmppc_slb *slbe;
@@ -670,6 +683,7 @@ void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu)
        mmu->slbmte = kvmppc_mmu_book3s_64_slbmte;
        mmu->slbmfee = kvmppc_mmu_book3s_64_slbmfee;
        mmu->slbmfev = kvmppc_mmu_book3s_64_slbmfev;
+       mmu->slbfee = kvmppc_mmu_book3s_64_slbfee;
        mmu->slbie = kvmppc_mmu_book3s_64_slbie;
        mmu->slbia = kvmppc_mmu_book3s_64_slbia;
        mmu->xlate = kvmppc_mmu_book3s_64_xlate;
index 8c7e933e942e5b56c42faf9eacdf08d5a183cde4..6ef7c5f00a49c0ac503a2d3eb2cf02f4ead324a9 100644 (file)
@@ -47,6 +47,7 @@
 #define OP_31_XOP_SLBMFEV      851
 #define OP_31_XOP_EIOIO                854
 #define OP_31_XOP_SLBMFEE      915
+#define OP_31_XOP_SLBFEE       979
 
 #define OP_31_XOP_TBEGIN       654
 #define OP_31_XOP_TABORT       910
@@ -416,6 +417,23 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
                        vcpu->arch.mmu.slbia(vcpu);
                        break;
+               case OP_31_XOP_SLBFEE:
+                       if (!(inst & 1) || !vcpu->arch.mmu.slbfee) {
+                               return EMULATE_FAIL;
+                       } else {
+                               ulong b, t;
+                               ulong cr = kvmppc_get_cr(vcpu) & ~CR0_MASK;
+
+                               b = kvmppc_get_gpr(vcpu, rb);
+                               if (!vcpu->arch.mmu.slbfee(vcpu, b, &t))
+                                       cr |= 2 << CR0_SHIFT;
+                               kvmppc_set_gpr(vcpu, rt, t);
+                               /* copy XER[SO] bit to CR0[SO] */
+                               cr |= (vcpu->arch.regs.xer & 0x80000000) >>
+                                       (31 - CR0_SHIFT);
+                               kvmppc_set_cr(vcpu, cr);
+                       }
+                       break;
                case OP_31_XOP_SLBMFEE:
                        if (!vcpu->arch.mmu.slbmfee) {
                                emulated = EMULATE_FAIL;