]> 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 63844b95c22c9902df769928313b988ee7d7667b..12b970701c264071b2d2f8fd77c23c16135018b7 100644 (file)
@@ -173,7 +173,8 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                return set_validity_icpt(scb_s, 0x0039U);
 
        /* copy only the wrapping keys */
-       if (read_guest_real(vcpu, crycb_addr + 72, &vsie_page->crycb, 56))
+       if (read_guest_real(vcpu, crycb_addr + 72,
+                           vsie_page->crycb.dea_wrapping_key_mask, 56))
                return set_validity_icpt(scb_s, 0x0035U);
 
        scb_s->ecb3 |= ecb3_flags;
@@ -829,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);
 
@@ -857,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();
@@ -1004,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;
        }
 
@@ -1121,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);