]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/kvm/booke_emulate.c
Merge commit 'torture.2015.02.23a' into core/rcu
[karo-tx-linux.git] / arch / powerpc / kvm / booke_emulate.c
index 28c158881d23f7f87daf87e7c2ce8731775d5630..a82f64502de124c6df3a899cac632548353048d5 100644 (file)
@@ -25,6 +25,7 @@
 
 #define OP_19_XOP_RFI     50
 #define OP_19_XOP_RFCI    51
+#define OP_19_XOP_RFDI    39
 
 #define OP_31_XOP_MFMSR   83
 #define OP_31_XOP_WRTEE   131
@@ -37,6 +38,12 @@ static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
        kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1);
 }
 
+static void kvmppc_emul_rfdi(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.pc = vcpu->arch.dsrr0;
+       kvmppc_set_msr(vcpu, vcpu->arch.dsrr1);
+}
+
 static void kvmppc_emul_rfci(struct kvm_vcpu *vcpu)
 {
        vcpu->arch.pc = vcpu->arch.csrr0;
@@ -65,6 +72,12 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        *advance = 0;
                        break;
 
+               case OP_19_XOP_RFDI:
+                       kvmppc_emul_rfdi(vcpu);
+                       kvmppc_set_exit_type(vcpu, EMULATED_RFDI_EXITS);
+                       *advance = 0;
+                       break;
+
                default:
                        emulated = EMULATE_FAIL;
                        break;
@@ -118,6 +131,7 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 {
        int emulated = EMULATE_DONE;
+       bool debug_inst = false;
 
        switch (sprn) {
        case SPRN_DEAR:
@@ -132,14 +146,128 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
        case SPRN_CSRR1:
                vcpu->arch.csrr1 = spr_val;
                break;
+       case SPRN_DSRR0:
+               vcpu->arch.dsrr0 = spr_val;
+               break;
+       case SPRN_DSRR1:
+               vcpu->arch.dsrr1 = spr_val;
+               break;
+       case SPRN_IAC1:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.iac1 = spr_val;
+               break;
+       case SPRN_IAC2:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.iac2 = spr_val;
+               break;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       case SPRN_IAC3:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.iac3 = spr_val;
+               break;
+       case SPRN_IAC4:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.iac4 = spr_val;
+               break;
+#endif
+       case SPRN_DAC1:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.dac1 = spr_val;
+               break;
+       case SPRN_DAC2:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.dac2 = spr_val;
+               break;
        case SPRN_DBCR0:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               spr_val &= (DBCR0_IDM | DBCR0_IC | DBCR0_BT | DBCR0_TIE |
+                       DBCR0_IAC1 | DBCR0_IAC2 | DBCR0_IAC3 | DBCR0_IAC4  |
+                       DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W);
+
                vcpu->arch.dbg_reg.dbcr0 = spr_val;
                break;
        case SPRN_DBCR1:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
                vcpu->arch.dbg_reg.dbcr1 = spr_val;
                break;
+       case SPRN_DBCR2:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
+               debug_inst = true;
+               vcpu->arch.dbg_reg.dbcr2 = spr_val;
+               break;
        case SPRN_DBSR:
+               /*
+                * If userspace is debugging guest then guest
+                * can not access debug registers.
+                */
+               if (vcpu->guest_debug)
+                       break;
+
                vcpu->arch.dbsr &= ~spr_val;
+               if (!(vcpu->arch.dbsr & ~DBSR_IDE))
+                       kvmppc_core_dequeue_debug(vcpu);
                break;
        case SPRN_TSR:
                kvmppc_clr_tsr_bits(vcpu, spr_val);
@@ -252,6 +380,10 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                emulated = EMULATE_FAIL;
        }
 
+       if (debug_inst) {
+               current->thread.debug = vcpu->arch.dbg_reg;
+               switch_booke_debug_regs(&vcpu->arch.dbg_reg);
+       }
        return emulated;
 }
 
@@ -278,12 +410,43 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
        case SPRN_CSRR1:
                *spr_val = vcpu->arch.csrr1;
                break;
+       case SPRN_DSRR0:
+               *spr_val = vcpu->arch.dsrr0;
+               break;
+       case SPRN_DSRR1:
+               *spr_val = vcpu->arch.dsrr1;
+               break;
+       case SPRN_IAC1:
+               *spr_val = vcpu->arch.dbg_reg.iac1;
+               break;
+       case SPRN_IAC2:
+               *spr_val = vcpu->arch.dbg_reg.iac2;
+               break;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       case SPRN_IAC3:
+               *spr_val = vcpu->arch.dbg_reg.iac3;
+               break;
+       case SPRN_IAC4:
+               *spr_val = vcpu->arch.dbg_reg.iac4;
+               break;
+#endif
+       case SPRN_DAC1:
+               *spr_val = vcpu->arch.dbg_reg.dac1;
+               break;
+       case SPRN_DAC2:
+               *spr_val = vcpu->arch.dbg_reg.dac2;
+               break;
        case SPRN_DBCR0:
                *spr_val = vcpu->arch.dbg_reg.dbcr0;
+               if (vcpu->guest_debug)
+                       *spr_val = *spr_val | DBCR0_EDM;
                break;
        case SPRN_DBCR1:
                *spr_val = vcpu->arch.dbg_reg.dbcr1;
                break;
+       case SPRN_DBCR2:
+               *spr_val = vcpu->arch.dbg_reg.dbcr2;
+               break;
        case SPRN_DBSR:
                *spr_val = vcpu->arch.dbsr;
                break;