]> Pileus Git - ~andy/linux/blobdiff - arch/powerpc/kvm/book3s.c
KVM: PPC: Add PV guest critical sections
[~andy/linux] / arch / powerpc / kvm / book3s.c
index 5cb5f0d9381f4407e2fe5bdf5040ead997dc00aa..d6227ff0ceae7e8e8a75dbcee7d636ed6c8260f4 100644 (file)
@@ -251,14 +251,28 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
        int deliver = 1;
        int vec = 0;
        ulong flags = 0ULL;
+       ulong crit_raw = vcpu->arch.shared->critical;
+       ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+       bool crit;
+
+       /* Truncate crit indicators in 32 bit mode */
+       if (!(vcpu->arch.shared->msr & MSR_SF)) {
+               crit_raw &= 0xffffffff;
+               crit_r1 &= 0xffffffff;
+       }
+
+       /* Critical section when crit == r1 */
+       crit = (crit_raw == crit_r1);
+       /* ... and we're in supervisor mode */
+       crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
 
        switch (priority) {
        case BOOK3S_IRQPRIO_DECREMENTER:
-               deliver = vcpu->arch.shared->msr & MSR_EE;
+               deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
                vec = BOOK3S_INTERRUPT_DECREMENTER;
                break;
        case BOOK3S_IRQPRIO_EXTERNAL:
-               deliver = vcpu->arch.shared->msr & MSR_EE;
+               deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
                vec = BOOK3S_INTERRUPT_EXTERNAL;
                break;
        case BOOK3S_IRQPRIO_SYSTEM_RESET: