arch/s390/kvm/pv.c

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

File Facts

System
Linux kernel
Corpus path
arch/s390/kvm/pv.c
Extension
.c
Size
30631 bytes
Lines
1064
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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

struct pv_make_secure {
	void *uvcb;
	struct folio *folio;
	struct kvm *kvm;
	int rc;
	bool needs_export;
};

static int __kvm_s390_pv_make_secure(struct guest_fault *f, struct folio *folio)
{
	struct pv_make_secure *priv = f->priv;
	int rc;

	if (priv->needs_export)
		uv_convert_from_secure(folio_to_phys(folio));

	if (folio_test_hugetlb(folio))
		return -EFAULT;
	if (folio_test_large(folio))
		return -E2BIG;

	if (!f->page)
		folio_get(folio);
	rc = __make_folio_secure(folio, priv->uvcb);
	if (!f->page)
		folio_put(folio);

	return rc;
}

static void _kvm_s390_pv_make_secure(struct guest_fault *f)
{
	struct pv_make_secure *priv = f->priv;
	struct folio *folio;
	spinlock_t *ptl;	/* pte lock from try_get_locked_pte() */
	pte_t *ptep;

	folio = pfn_folio(f->pfn);
	priv->rc = -EAGAIN;

	if (!mmap_read_trylock(priv->kvm->mm))
		return;

	ptep = try_get_locked_pte(priv->kvm->mm, gfn_to_hva(priv->kvm, f->gfn), &ptl);
	if (IS_ERR_VALUE(ptep)) {
		priv->rc = PTR_ERR(ptep);
		goto out;
	}

	if (folio_trylock(folio)) {
		priv->rc = __kvm_s390_pv_make_secure(f, folio);
		if (priv->rc == -E2BIG || priv->rc == -EBUSY) {
			priv->folio = folio;
			folio_get(folio);
		}
		folio_unlock(folio);
	}

	if (ptep)
		pte_unmap_unlock(ptep, ptl);
out:
	mmap_read_unlock(priv->kvm->mm);
}

/**
 * kvm_s390_pv_make_secure() - make one guest page secure
 * @kvm: the guest
 * @gaddr: the guest address that needs to be made secure
 * @uvcb: the UVCB specifying which operation needs to be performed
 *
 * Context: needs to be called with kvm->srcu held.
 * Return: 0 on success, < 0 in case of error.
 */
int kvm_s390_pv_make_secure(struct kvm *kvm, unsigned long gaddr, void *uvcb)
{
	struct pv_make_secure priv = { .uvcb = uvcb, .kvm = kvm, };
	struct guest_fault f = {
		.write_attempt = true,
		.gfn = gpa_to_gfn(gaddr),
		.callback = _kvm_s390_pv_make_secure,
		.priv = &priv,
	};
	int rc;

	lockdep_assert_held(&kvm->srcu);

	priv.needs_export = should_export_before_import(uvcb, kvm->mm);

	scoped_guard(mutex, &kvm->arch.pv.import_lock) {
		rc = kvm_s390_faultin_gfn(NULL, kvm, &f);

Annotation

Implementation Notes