#include <linux/pagewalk.h>
#include <linux/sched/mm.h>
#include <linux/mmu_notifier.h>
+#include <asm/gmap_helpers.h>
#include "kvm-s390.h"
#include "dat.h"
#include "gaccess.h"
struct pv_make_secure {
void *uvcb;
struct folio *folio;
+ struct kvm *kvm;
int rc;
bool needs_export;
};
{
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) {
}
folio_unlock(folio);
}
+
+ if (ptep)
+ pte_unmap_unlock(ptep, ptl);
+out:
+ mmap_read_unlock(priv->kvm->mm);
}
/**
*/
int kvm_s390_pv_make_secure(struct kvm *kvm, unsigned long gaddr, void *uvcb)
{
- struct pv_make_secure priv = { .uvcb = uvcb };
+ struct pv_make_secure priv = { .uvcb = uvcb, .kvm = kvm, };
struct guest_fault f = {
.write_attempt = true,
.gfn = gpa_to_gfn(gaddr),