|
@@ -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);
|