arch/s390/kvm/faultin.c

Source file repositories/reference/linux-study-clean/arch/s390/kvm/faultin.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kvm/faultin.c
Extension
.c
Size
3838 bytes
Lines
149
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (f->pfn == KVM_PFN_ERR_NEEDS_IO) {
			if (unlikely(!f->attempt_pfault))
				return -EAGAIN;
			if (unlikely(!vcpu))
				return -EINVAL;
			trace_kvm_s390_major_guest_pfault(vcpu);
			if (kvm_arch_setup_async_pf(vcpu))
				return 0;
			vcpu->stat.pfault_sync++;
			/* Could not setup async pfault, try again synchronously. */
			foll &= ~FOLL_NOWAIT;
			f->pfn = __kvm_faultin_pfn(slot, f->gfn, foll, &f->writable, &f->page);
		}

		/* Access outside memory, addressing exception. */
		if (is_noslot_pfn(f->pfn))
			return PGM_ADDRESSING;
		/* Signal pending: try again. */
		if (f->pfn == KVM_PFN_ERR_SIGPENDING)
			return -EAGAIN;
		/* 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;
		/* Any other error. */
		if (is_error_pfn(f->pfn))
			return -EFAULT;

		/* Loop, release the faulted page. */
		if (mmu_invalidate_retry_gfn_unsafe(kvm, inv_seq, f->gfn)) {
			kvm_release_faultin_page(kvm, f->page, true, false);
			continue;
		}

		scoped_guard(read_lock, &kvm->mmu_lock) {
			if (!mmu_invalidate_retry_gfn(kvm, inv_seq, f->gfn)) {
				f->valid = true;
				rc = gmap_link(mc, kvm->arch.gmap, f, slot);
			}
			kvm_release_faultin_page(kvm, f->page, !!rc, f->write_attempt);
		}

		if (rc == -ENOMEM) {
			rc = kvm_s390_mmu_cache_topup(mc);
			if (rc)
				return rc;
			rc = -EAGAIN;
		}
	}

	return rc;
}

int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w)
{
	struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
	int foll = w ? FOLL_WRITE : 0;

	f->write_attempt = w;
	f->gfn = gfn;
	f->pfn = __kvm_faultin_pfn(slot, gfn, foll, &f->writable, &f->page);
	if (is_noslot_pfn(f->pfn))
		return PGM_ADDRESSING;
	if (is_sigpending_pfn(f->pfn))
		return -EINTR;
	if (f->pfn == KVM_PFN_ERR_NEEDS_IO)
		return -EAGAIN;
	if (is_error_pfn(f->pfn))
		return -EFAULT;

	f->valid = true;
	return 0;
}

Annotation

Implementation Notes