]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - arch/s390/kvm/vsie.c
KVM: s390: vsie: simulate VCPU SIE entry/exit
[linux.git] / arch / s390 / kvm / vsie.c
index a2b28cd1e3fedb2bdcc6dbb1cff530ba0e3371a7..12b970701c264071b2d2f8fd77c23c16135018b7 100644 (file)
@@ -830,7 +830,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
        struct kvm_s390_sie_block *scb_o = vsie_page->scb_o;
        int guest_bp_isolation;
-       int rc;
+       int rc = 0;
 
        handle_last_fault(vcpu, vsie_page);
 
@@ -858,7 +858,18 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        guest_enter_irqoff();
        local_irq_enable();
 
-       rc = sie64a(scb_s, vcpu->run->s.regs.gprs);
+       /*
+        * Simulate a SIE entry of the VCPU (see sie64a), so VCPU blocking
+        * and VCPU requests also hinder the vSIE from running and lead
+        * to an immediate exit. kvm_s390_vsie_kick() has to be used to
+        * also kick the vSIE.
+        */
+       vcpu->arch.sie_block->prog0c |= PROG_IN_SIE;
+       barrier();
+       if (!kvm_s390_vcpu_sie_inhibited(vcpu))
+               rc = sie64a(scb_s, vcpu->run->s.regs.gprs);
+       barrier();
+       vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE;
 
        local_irq_disable();
        guest_exit_irqoff();
@@ -1005,7 +1016,8 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                if (rc == -EAGAIN)
                        rc = 0;
                if (rc || scb_s->icptcode || signal_pending(current) ||
-                   kvm_s390_vcpu_has_irq(vcpu, 0))
+                   kvm_s390_vcpu_has_irq(vcpu, 0) ||
+                   kvm_s390_vcpu_sie_inhibited(vcpu))
                        break;
        }
 
@@ -1122,7 +1134,8 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu)
        if (unlikely(scb_addr & 0x1ffUL))
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       if (signal_pending(current) || kvm_s390_vcpu_has_irq(vcpu, 0))
+       if (signal_pending(current) || kvm_s390_vcpu_has_irq(vcpu, 0) ||
+           kvm_s390_vcpu_sie_inhibited(vcpu))
                return 0;
 
        vsie_page = get_vsie_page(vcpu->kvm, scb_addr);