If a signal is pending while trying to fault-in a page, return -EINTR instead of -EAGAIN. Also fix unpack_one() and handle_mvpg_pei() so that they can handle -EINTR properly. Signed-off-by: Claudio Imbrenda Fixes: e907ae530133 ("KVM: s390: Add helper functions for fault handling") --- arch/s390/kvm/faultin.c | 4 ++-- arch/s390/kvm/intercept.c | 23 +++++++++++++---------- arch/s390/kvm/pv.c | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/arch/s390/kvm/faultin.c b/arch/s390/kvm/faultin.c index fee80047bd94..4ff4c5970956 100644 --- a/arch/s390/kvm/faultin.c +++ b/arch/s390/kvm/faultin.c @@ -92,8 +92,8 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa if (is_noslot_pfn(f->pfn)) return PGM_ADDRESSING; /* Signal pending: try again. */ - if (f->pfn == KVM_PFN_ERR_SIGPENDING) - return -EAGAIN; + if (is_sigpending_pfn(f->pfn)) + return -EINTR; /* Check if it's read-only memory; don't try to actually handle that case. */ if (f->pfn == KVM_PFN_ERR_RO_FAULT) return -EOPNOTSUPP; diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 1980df61ef30..a40fe2a10cbf 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -369,27 +369,30 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); - do { - rc = kvm_s390_faultin_gfn_simple(vcpu, NULL, gpa_to_gfn(srcaddr), false); - } while (rc == -EAGAIN); - if (rc) - return rc; - - /* Ensure that the source is paged-in, no actual access -> no key checking */ + /* Ensure that the destination is paged-in, no actual access -> no key checking */ rc = guest_translate_address_with_key(vcpu, vcpu->run->s.regs.gprs[reg1], reg1, &dstaddr, GACC_STORE, 0); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); + /* + * If an error happens below, the instruction needs to be retried. + * Positive error codes are impossible; addressing exceptions would + * have been discovered and reported above. + */ + kvm_s390_retry_instr(vcpu); + do { - rc = kvm_s390_faultin_gfn_simple(vcpu, NULL, gpa_to_gfn(dstaddr), true); + rc = kvm_s390_faultin_gfn_simple(vcpu, NULL, gpa_to_gfn(srcaddr), false); } while (rc == -EAGAIN); if (rc) return rc; - kvm_s390_retry_instr(vcpu); + do { + rc = kvm_s390_faultin_gfn_simple(vcpu, NULL, gpa_to_gfn(dstaddr), true); + } while (rc == -EAGAIN); - return 0; + return rc; } static int handle_partial_execution(struct kvm_vcpu *vcpu) diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c index 1beacc841ca8..dc204b521052 100644 --- a/arch/s390/kvm/pv.c +++ b/arch/s390/kvm/pv.c @@ -809,7 +809,7 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak, return -EAGAIN; } - if (ret && ret != -EAGAIN) + if (ret && ret != -EAGAIN && ret != -EINTR) KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x", uvcb.gaddr, *rc, *rrc); return ret; -- 2.55.0