KVM: PPC: Move mtspr/mfspr emulation into own functions
authorAlexander Graf <agraf@suse.de>
Sat, 6 Oct 2012 21:19:01 +0000 (23:19 +0200)
committerAlexander Graf <agraf@suse.de>
Tue, 30 Oct 2012 09:54:51 +0000 (10:54 +0100)
The mtspr/mfspr emulation code became quite big over time. Move it
into its own function so things stay more readable.

Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/kvm/emulate.c

index ee04abaefe233c89e692a9e1a84e4686d4da8030..b0855e5d8905ee50e6422ca9edfc37aa952f6b21 100644 (file)
@@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
        return vcpu->arch.dec - jd;
 }
 
+static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+       enum emulation_result emulated = EMULATE_DONE;
+       ulong spr_val = kvmppc_get_gpr(vcpu, rs);
+
+       switch (sprn) {
+       case SPRN_SRR0:
+               vcpu->arch.shared->srr0 = spr_val;
+               break;
+       case SPRN_SRR1:
+               vcpu->arch.shared->srr1 = spr_val;
+               break;
+
+       /* XXX We need to context-switch the timebase for
+        * watchdog and FIT. */
+       case SPRN_TBWL: break;
+       case SPRN_TBWU: break;
+
+       case SPRN_MSSSR0: break;
+
+       case SPRN_DEC:
+               vcpu->arch.dec = spr_val;
+               kvmppc_emulate_dec(vcpu);
+               break;
+
+       case SPRN_SPRG0:
+               vcpu->arch.shared->sprg0 = spr_val;
+               break;
+       case SPRN_SPRG1:
+               vcpu->arch.shared->sprg1 = spr_val;
+               break;
+       case SPRN_SPRG2:
+               vcpu->arch.shared->sprg2 = spr_val;
+               break;
+       case SPRN_SPRG3:
+               vcpu->arch.shared->sprg3 = spr_val;
+               break;
+
+       default:
+               emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
+                                                    spr_val);
+               if (emulated == EMULATE_FAIL)
+                       printk(KERN_INFO "mtspr: unknown spr "
+                               "0x%x\n", sprn);
+               break;
+       }
+
+       kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+
+       return emulated;
+}
+
+static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+       enum emulation_result emulated = EMULATE_DONE;
+       ulong spr_val = 0;
+
+       switch (sprn) {
+       case SPRN_SRR0:
+               spr_val = vcpu->arch.shared->srr0;
+               break;
+       case SPRN_SRR1:
+               spr_val = vcpu->arch.shared->srr1;
+               break;
+       case SPRN_PVR:
+               spr_val = vcpu->arch.pvr;
+               break;
+       case SPRN_PIR:
+               spr_val = vcpu->vcpu_id;
+               break;
+       case SPRN_MSSSR0:
+               spr_val = 0;
+               break;
+
+       /* Note: mftb and TBRL/TBWL are user-accessible, so
+        * the guest can always access the real TB anyways.
+        * In fact, we probably will never see these traps. */
+       case SPRN_TBWL:
+               spr_val = get_tb() >> 32;
+               break;
+       case SPRN_TBWU:
+               spr_val = get_tb();
+               break;
+
+       case SPRN_SPRG0:
+               spr_val = vcpu->arch.shared->sprg0;
+               break;
+       case SPRN_SPRG1:
+               spr_val = vcpu->arch.shared->sprg1;
+               break;
+       case SPRN_SPRG2:
+               spr_val = vcpu->arch.shared->sprg2;
+               break;
+       case SPRN_SPRG3:
+               spr_val = vcpu->arch.shared->sprg3;
+               break;
+       /* Note: SPRG4-7 are user-readable, so we don't get
+        * a trap. */
+
+       case SPRN_DEC:
+               spr_val = kvmppc_get_dec(vcpu, get_tb());
+               break;
+       default:
+               emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
+                                                    &spr_val);
+               if (unlikely(emulated == EMULATE_FAIL)) {
+                       printk(KERN_INFO "mfspr: unknown spr "
+                               "0x%x\n", sprn);
+               }
+               break;
+       }
+
+       if (emulated == EMULATE_DONE)
+               kvmppc_set_gpr(vcpu, rt, spr_val);
+       kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+
+       return emulated;
+}
+
 /* XXX to do:
  * lhax
  * lhaux
@@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
        int sprn = get_sprn(inst);
        enum emulation_result emulated = EMULATE_DONE;
        int advance = 1;
-       ulong spr_val = 0;
 
        /* this default type might be overwritten by subcategories */
        kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        break;
 
                case OP_31_XOP_MFSPR:
-                       switch (sprn) {
-                       case SPRN_SRR0:
-                               spr_val = vcpu->arch.shared->srr0;
-                               break;
-                       case SPRN_SRR1:
-                               spr_val = vcpu->arch.shared->srr1;
-                               break;
-                       case SPRN_PVR:
-                               spr_val = vcpu->arch.pvr;
-                               break;
-                       case SPRN_PIR:
-                               spr_val = vcpu->vcpu_id;
-                               break;
-                       case SPRN_MSSSR0:
-                               spr_val = 0;
-                               break;
-
-                       /* Note: mftb and TBRL/TBWL are user-accessible, so
-                        * the guest can always access the real TB anyways.
-                        * In fact, we probably will never see these traps. */
-                       case SPRN_TBWL:
-                               spr_val = get_tb() >> 32;
-                               break;
-                       case SPRN_TBWU:
-                               spr_val = get_tb();
-                               break;
-
-                       case SPRN_SPRG0:
-                               spr_val = vcpu->arch.shared->sprg0;
-                               break;
-                       case SPRN_SPRG1:
-                               spr_val = vcpu->arch.shared->sprg1;
-                               break;
-                       case SPRN_SPRG2:
-                               spr_val = vcpu->arch.shared->sprg2;
-                               break;
-                       case SPRN_SPRG3:
-                               spr_val = vcpu->arch.shared->sprg3;
-                               break;
-                       /* Note: SPRG4-7 are user-readable, so we don't get
-                        * a trap. */
-
-                       case SPRN_DEC:
-                               spr_val = kvmppc_get_dec(vcpu, get_tb());
-                               break;
-                       default:
-                               emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
-                                                                    &spr_val);
-                               if (unlikely(emulated == EMULATE_FAIL)) {
-                                       printk(KERN_INFO "mfspr: unknown spr "
-                                               "0x%x\n", sprn);
-                               }
-                               break;
-                       }
-                       kvmppc_set_gpr(vcpu, rt, spr_val);
-                       kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+                       emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
                        break;
 
                case OP_31_XOP_STHX:
@@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        break;
 
                case OP_31_XOP_MTSPR:
-                       spr_val = kvmppc_get_gpr(vcpu, rs);
-                       switch (sprn) {
-                       case SPRN_SRR0:
-                               vcpu->arch.shared->srr0 = spr_val;
-                               break;
-                       case SPRN_SRR1:
-                               vcpu->arch.shared->srr1 = spr_val;
-                               break;
-
-                       /* XXX We need to context-switch the timebase for
-                        * watchdog and FIT. */
-                       case SPRN_TBWL: break;
-                       case SPRN_TBWU: break;
-
-                       case SPRN_MSSSR0: break;
-
-                       case SPRN_DEC:
-                               vcpu->arch.dec = spr_val;
-                               kvmppc_emulate_dec(vcpu);
-                               break;
-
-                       case SPRN_SPRG0:
-                               vcpu->arch.shared->sprg0 = spr_val;
-                               break;
-                       case SPRN_SPRG1:
-                               vcpu->arch.shared->sprg1 = spr_val;
-                               break;
-                       case SPRN_SPRG2:
-                               vcpu->arch.shared->sprg2 = spr_val;
-                               break;
-                       case SPRN_SPRG3:
-                               vcpu->arch.shared->sprg3 = spr_val;
-                               break;
-
-                       default:
-                               emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
-                                                                    spr_val);
-                               if (emulated == EMULATE_FAIL)
-                                       printk(KERN_INFO "mtspr: unknown spr "
-                                               "0x%x\n", sprn);
-                               break;
-                       }
-                       kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+                       emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
                        break;
 
                case OP_31_XOP_DCBI: