OSDN Git Service

KVM: PPC: e500: Add emulation helper for getting instruction ea
authorMihai Caraman <mihai.caraman@freescale.com>
Thu, 11 Oct 2012 06:13:22 +0000 (06:13 +0000)
committerAlexander Graf <agraf@suse.de>
Thu, 6 Dec 2012 00:34:12 +0000 (01:34 +0100)
Add emulation helper for getting instruction ea and refactor tlb instruction
emulation to use it.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
[agraf: keep rt variable around]
Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/e500.h
arch/powerpc/kvm/e500_emulate.c
arch/powerpc/kvm/e500_tlb.c

index 1ca31e9..d55a2b2 100644 (file)
@@ -295,4 +295,15 @@ static inline void kvmppc_lazy_ee_enable(void)
 #endif
 }
 
+static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
+{
+       ulong ea;
+
+       ea = kvmppc_get_gpr(vcpu, rb);
+       if (ra)
+               ea += kvmppc_get_gpr(vcpu, ra);
+
+       return ea;
+}
+
 #endif /* __POWERPC_KVM_PPC_H__ */
index d162286..32e98a7 100644 (file)
@@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
                                ulong value);
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
 int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
 int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
 
index e04b0ef..e78f353 100644 (file)
@@ -89,6 +89,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
        int ra = get_ra(inst);
        int rb = get_rb(inst);
        int rt = get_rt(inst);
+       gva_t ea;
 
        switch (get_op(inst)) {
        case 31:
@@ -113,15 +114,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        break;
 
                case XOP_TLBSX:
-                       emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
+                       ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+                       emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
                        break;
 
-               case XOP_TLBILX:
-                       emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
+               case XOP_TLBILX: {
+                       int type = rt & 0x3;
+                       ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+                       emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea);
                        break;
+               }
 
                case XOP_TLBIVAX:
-                       emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
+                       ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+                       emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
                        break;
 
                default:
index 5532bfb..7a14721 100644 (file)
@@ -689,14 +689,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
        return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        unsigned int ia;
        int esel, tlbsel;
-       gva_t ea;
-
-       ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
 
        ia = (ea >> 2) & 0x1;
 
@@ -723,7 +720,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 }
 
 static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
-                      int pid, int rt)
+                      int pid, int type)
 {
        struct kvm_book3e_206_tlb_entry *tlbe;
        int tid, esel;
@@ -732,7 +729,7 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
        for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
                tlbe = get_entry(vcpu_e500, tlbsel, esel);
                tid = get_tlb_tid(tlbe);
-               if (rt == 0 || tid == pid) {
+               if (type == 0 || tid == pid) {
                        inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
                }
@@ -740,14 +737,9 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 }
 
 static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
-                      int ra, int rb)
+                      gva_t ea)
 {
        int tlbsel, esel;
-       gva_t ea;
-
-       ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
-       if (ra)
-               ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);
 
        for (tlbsel = 0; tlbsel < 2; tlbsel++) {
                esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
@@ -759,16 +751,16 @@ static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
        }
 }
 
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int pid = get_cur_spid(vcpu);
 
-       if (rt == 0 || rt == 1) {
-               tlbilx_all(vcpu_e500, 0, pid, rt);
-               tlbilx_all(vcpu_e500, 1, pid, rt);
-       } else if (rt == 3) {
-               tlbilx_one(vcpu_e500, pid, ra, rb);
+       if (type == 0 || type == 1) {
+               tlbilx_all(vcpu_e500, 0, pid, type);
+               tlbilx_all(vcpu_e500, 1, pid, type);
+       } else if (type == 3) {
+               tlbilx_one(vcpu_e500, pid, ea);
        }
 
        return EMULATE_DONE;
@@ -793,16 +785,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int as = !!get_cur_sas(vcpu);
        unsigned int pid = get_cur_spid(vcpu);
        int esel, tlbsel;
        struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
-       gva_t ea;
-
-       ea = kvmppc_get_gpr(vcpu, rb);
 
        for (tlbsel = 0; tlbsel < 2; tlbsel++) {
                esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);