1*1b09c13cSSteffen Eiden // SPDX-License-Identifier: GPL-2.0 2*1b09c13cSSteffen Eiden /* 3*1b09c13cSSteffen Eiden * KVM guest fault handling. 4*1b09c13cSSteffen Eiden * 5*1b09c13cSSteffen Eiden * Copyright IBM Corp. 2025 6*1b09c13cSSteffen Eiden * Author(s): Claudio Imbrenda <imbrenda@linux.ibm.com> 7*1b09c13cSSteffen Eiden */ 8*1b09c13cSSteffen Eiden #include <linux/kvm_types.h> 9*1b09c13cSSteffen Eiden #include <linux/kvm_host.h> 10*1b09c13cSSteffen Eiden 11*1b09c13cSSteffen Eiden #include "gmap.h" 12*1b09c13cSSteffen Eiden #include "faultin.h" 13*1b09c13cSSteffen Eiden 14*1b09c13cSSteffen Eiden bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu); 15*1b09c13cSSteffen Eiden #define CREATE_TRACE_POINTS 16*1b09c13cSSteffen Eiden #include "trace_gmap.h" 17*1b09c13cSSteffen Eiden 18*1b09c13cSSteffen Eiden /* 19*1b09c13cSSteffen Eiden * kvm_s390_faultin_gfn() - handle a dat fault. 20*1b09c13cSSteffen Eiden * @vcpu: The vCPU whose gmap is to be fixed up, or NULL if operating on the VM. 21*1b09c13cSSteffen Eiden * @kvm: The VM whose gmap is to be fixed up, or NULL if operating on a vCPU. 22*1b09c13cSSteffen Eiden * @f: The guest fault that needs to be resolved. 23*1b09c13cSSteffen Eiden * 24*1b09c13cSSteffen Eiden * Return: 25*1b09c13cSSteffen Eiden * * 0 on success 26*1b09c13cSSteffen Eiden * * < 0 in case of error 27*1b09c13cSSteffen Eiden * * > 0 in case of guest exceptions 28*1b09c13cSSteffen Eiden * 29*1b09c13cSSteffen Eiden * Context: 30*1b09c13cSSteffen Eiden * * The mm lock must not be held before calling 31*1b09c13cSSteffen Eiden * * kvm->srcu must be held 32*1b09c13cSSteffen Eiden * * may sleep 33*1b09c13cSSteffen Eiden */ 34*1b09c13cSSteffen Eiden int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fault *f) 35*1b09c13cSSteffen Eiden { 36*1b09c13cSSteffen Eiden struct kvm_s390_mmu_cache *local_mc __free(kvm_s390_mmu_cache) = NULL; 37*1b09c13cSSteffen Eiden struct kvm_s390_mmu_cache *mc = NULL; 38*1b09c13cSSteffen Eiden struct kvm_memory_slot *slot; 39*1b09c13cSSteffen Eiden unsigned long inv_seq; 40*1b09c13cSSteffen Eiden int rc = -EAGAIN; 41*1b09c13cSSteffen Eiden int foll; 42*1b09c13cSSteffen Eiden 43*1b09c13cSSteffen Eiden foll = f->write_attempt ? FOLL_WRITE : 0; 44*1b09c13cSSteffen Eiden foll |= f->attempt_pfault ? FOLL_NOWAIT : 0; 45*1b09c13cSSteffen Eiden 46*1b09c13cSSteffen Eiden if (vcpu) { 47*1b09c13cSSteffen Eiden kvm = vcpu->kvm; 48*1b09c13cSSteffen Eiden mc = vcpu->arch.mc; 49*1b09c13cSSteffen Eiden } 50*1b09c13cSSteffen Eiden 51*1b09c13cSSteffen Eiden lockdep_assert_held(&kvm->srcu); 52*1b09c13cSSteffen Eiden 53*1b09c13cSSteffen Eiden scoped_guard(read_lock, &kvm->mmu_lock) { 54*1b09c13cSSteffen Eiden if (gmap_try_fixup_minor(kvm->arch.gmap, f) == 0) 55*1b09c13cSSteffen Eiden return 0; 56*1b09c13cSSteffen Eiden } 57*1b09c13cSSteffen Eiden 58*1b09c13cSSteffen Eiden if (!mc) { 59*1b09c13cSSteffen Eiden local_mc = kvm_s390_new_mmu_cache(); 60*1b09c13cSSteffen Eiden if (!local_mc) 61*1b09c13cSSteffen Eiden return -ENOMEM; 62*1b09c13cSSteffen Eiden mc = local_mc; 63*1b09c13cSSteffen Eiden } 64*1b09c13cSSteffen Eiden 65*1b09c13cSSteffen Eiden while (rc == -EAGAIN) { 66*1b09c13cSSteffen Eiden f->valid = false; 67*1b09c13cSSteffen Eiden inv_seq = kvm->mmu_invalidate_seq; 68*1b09c13cSSteffen Eiden /* Pairs with the smp_wmb() in kvm_mmu_invalidate_end(). */ 69*1b09c13cSSteffen Eiden smp_rmb(); 70*1b09c13cSSteffen Eiden 71*1b09c13cSSteffen Eiden if (vcpu) 72*1b09c13cSSteffen Eiden slot = kvm_vcpu_gfn_to_memslot(vcpu, f->gfn); 73*1b09c13cSSteffen Eiden else 74*1b09c13cSSteffen Eiden slot = gfn_to_memslot(kvm, f->gfn); 75*1b09c13cSSteffen Eiden f->pfn = __kvm_faultin_pfn(slot, f->gfn, foll, &f->writable, &f->page); 76*1b09c13cSSteffen Eiden 77*1b09c13cSSteffen Eiden /* Needs I/O, try to setup async pfault (only possible with FOLL_NOWAIT). */ 78*1b09c13cSSteffen Eiden if (f->pfn == KVM_PFN_ERR_NEEDS_IO) { 79*1b09c13cSSteffen Eiden if (unlikely(!f->attempt_pfault)) 80*1b09c13cSSteffen Eiden return -EAGAIN; 81*1b09c13cSSteffen Eiden if (unlikely(!vcpu)) 82*1b09c13cSSteffen Eiden return -EINVAL; 83*1b09c13cSSteffen Eiden trace_kvm_s390_major_guest_pfault(vcpu); 84*1b09c13cSSteffen Eiden if (kvm_arch_setup_async_pf(vcpu)) 85*1b09c13cSSteffen Eiden return 0; 86*1b09c13cSSteffen Eiden vcpu->stat.pfault_sync++; 87*1b09c13cSSteffen Eiden /* Could not setup async pfault, try again synchronously. */ 88*1b09c13cSSteffen Eiden foll &= ~FOLL_NOWAIT; 89*1b09c13cSSteffen Eiden f->pfn = __kvm_faultin_pfn(slot, f->gfn, foll, &f->writable, &f->page); 90*1b09c13cSSteffen Eiden } 91*1b09c13cSSteffen Eiden 92*1b09c13cSSteffen Eiden /* Access outside memory, addressing exception. */ 93*1b09c13cSSteffen Eiden if (is_noslot_pfn(f->pfn)) 94*1b09c13cSSteffen Eiden return PGM_ADDRESSING; 95*1b09c13cSSteffen Eiden /* Fatal signal pending: bail out. */ 96*1b09c13cSSteffen Eiden if (is_sigpending_pfn(f->pfn)) 97*1b09c13cSSteffen Eiden return -EINTR; 98*1b09c13cSSteffen Eiden /* Check if it's read-only memory; don't try to actually handle that case. */ 99*1b09c13cSSteffen Eiden if (f->pfn == KVM_PFN_ERR_RO_FAULT) 100*1b09c13cSSteffen Eiden return -EOPNOTSUPP; 101*1b09c13cSSteffen Eiden /* Any other error. */ 102*1b09c13cSSteffen Eiden if (is_error_pfn(f->pfn)) 103*1b09c13cSSteffen Eiden return -EFAULT; 104*1b09c13cSSteffen Eiden 105*1b09c13cSSteffen Eiden /* Loop, release the faulted page. */ 106*1b09c13cSSteffen Eiden if (mmu_invalidate_retry_gfn_unsafe(kvm, inv_seq, f->gfn)) { 107*1b09c13cSSteffen Eiden kvm_release_faultin_page(kvm, f->page, true, false); 108*1b09c13cSSteffen Eiden continue; 109*1b09c13cSSteffen Eiden } 110*1b09c13cSSteffen Eiden 111*1b09c13cSSteffen Eiden scoped_guard(read_lock, &kvm->mmu_lock) { 112*1b09c13cSSteffen Eiden if (!mmu_invalidate_retry_gfn(kvm, inv_seq, f->gfn)) { 113*1b09c13cSSteffen Eiden f->valid = true; 114*1b09c13cSSteffen Eiden rc = gmap_link(mc, kvm->arch.gmap, f, slot); 115*1b09c13cSSteffen Eiden } 116*1b09c13cSSteffen Eiden kvm_release_faultin_page(kvm, f->page, !!rc, f->write_attempt); 117*1b09c13cSSteffen Eiden } 118*1b09c13cSSteffen Eiden 119*1b09c13cSSteffen Eiden if (rc == -ENOMEM) { 120*1b09c13cSSteffen Eiden rc = kvm_s390_mmu_cache_topup(mc); 121*1b09c13cSSteffen Eiden if (rc) 122*1b09c13cSSteffen Eiden return rc; 123*1b09c13cSSteffen Eiden rc = -EAGAIN; 124*1b09c13cSSteffen Eiden } 125*1b09c13cSSteffen Eiden } 126*1b09c13cSSteffen Eiden 127*1b09c13cSSteffen Eiden return rc; 128*1b09c13cSSteffen Eiden } 129*1b09c13cSSteffen Eiden 130*1b09c13cSSteffen Eiden int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w) 131*1b09c13cSSteffen Eiden { 132*1b09c13cSSteffen Eiden struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn); 133*1b09c13cSSteffen Eiden int foll = w ? FOLL_WRITE : 0; 134*1b09c13cSSteffen Eiden 135*1b09c13cSSteffen Eiden f->write_attempt = w; 136*1b09c13cSSteffen Eiden f->gfn = gfn; 137*1b09c13cSSteffen Eiden f->pfn = __kvm_faultin_pfn(slot, gfn, foll, &f->writable, &f->page); 138*1b09c13cSSteffen Eiden if (is_noslot_pfn(f->pfn)) 139*1b09c13cSSteffen Eiden return PGM_ADDRESSING; 140*1b09c13cSSteffen Eiden if (is_sigpending_pfn(f->pfn)) 141*1b09c13cSSteffen Eiden return -EINTR; 142*1b09c13cSSteffen Eiden if (f->pfn == KVM_PFN_ERR_NEEDS_IO) 143*1b09c13cSSteffen Eiden return -EAGAIN; 144*1b09c13cSSteffen Eiden if (is_error_pfn(f->pfn)) 145*1b09c13cSSteffen Eiden return -EFAULT; 146*1b09c13cSSteffen Eiden 147*1b09c13cSSteffen Eiden f->valid = true; 148*1b09c13cSSteffen Eiden return 0; 149*1b09c13cSSteffen Eiden } 150