aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
authorMark Brown <broonie@kernel.org>2026-05-29 22:46:50 +0100
committerMark Brown <broonie@kernel.org>2026-05-29 22:46:50 +0100
commit29fa9b4922922bd33cac81162dbf669bfb55a52d (patch)
tree1b69a4af640a25f012bab6652dee05ab1878f0d3 /arch
parent0ce0f7ee41c6e99f682a62e1d1363881fa18ff58 (diff)
parent68f8c9565c4391343aa3b77f7af642a366991405 (diff)
downloadlinux-next-history-29fa9b4922922bd33cac81162dbf669bfb55a52d.tar.gz
Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kvm/Kconfig1
-rw-r--r--arch/s390/kvm/dat.h1
-rw-r--r--arch/s390/kvm/gmap.c2
-rw-r--r--arch/s390/kvm/kvm-s390.c45
4 files changed, 49 insertions, 0 deletions
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index 5b835bc6a1941..8d3ee17a1bcbc 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -30,6 +30,7 @@ config KVM
select KVM_VFIO
select VIRT_XFER_TO_GUEST_WORK
select KVM_MMU_LOCKLESS_AGING
+ select KVM_GENERIC_PRE_FAULT_MEMORY
help
Support hosting paravirtualized guest machines using the SIE
virtualization capability on the mainframe. This should work
diff --git a/arch/s390/kvm/dat.h b/arch/s390/kvm/dat.h
index 873e13ac5a27f..fad605305e05c 100644
--- a/arch/s390/kvm/dat.h
+++ b/arch/s390/kvm/dat.h
@@ -501,6 +501,7 @@ struct guest_fault {
bool write_attempt; /* Write access attempted */
bool attempt_pfault; /* Attempt a pfault first */
bool valid; /* This entry contains valid data */
+ bool crste_region3; /* Whether crstep refers to a region3 entry */
void (*callback)(struct guest_fault *f);
void *priv;
};
diff --git a/arch/s390/kvm/gmap.c b/arch/s390/kvm/gmap.c
index 957126ab991ca..8fb684768eb6f 100644
--- a/arch/s390/kvm/gmap.c
+++ b/arch/s390/kvm/gmap.c
@@ -530,6 +530,7 @@ static int gmap_handle_minor_crste_fault(struct gmap *gmap, struct guest_fault *
f->pfn = PHYS_PFN(large_crste_to_phys(oldcrste, f->gfn));
f->writable = oldcrste.s.fc1.w;
+ f->crste_region3 = is_pud(oldcrste);
/* Appropriate permissions already (race with another handler), nothing to do. */
if (!oldcrste.h.i && !(f->write_attempt && oldcrste.h.p))
return 0;
@@ -689,6 +690,7 @@ static int _gmap_link(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, int leve
if (oldval.val != _CRSTE_EMPTY(oldval.h.tt).val &&
crste_origin_large(oldval) != crste_origin_large(newval))
return -EAGAIN;
+ f->crste_region3 = is_pud(newval);
} while (!gmap_crstep_xchg_atomic(gmap, f->crstep, oldval, newval, f->gfn));
if (f->callback)
f->callback(f);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index e09960c2e6ed1..f6521f16532ae 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -630,6 +630,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_S390_USER_OPEREXEC:
case KVM_CAP_S390_KEYOP:
case KVM_CAP_S390_VSIE_ESAMODE:
+ case KVM_CAP_PRE_FAULT_MEMORY:
r = 1;
break;
case KVM_CAP_SET_GUEST_DEBUG2:
@@ -5737,6 +5738,50 @@ out:
}
/**
+ * kvm_arch_vcpu_pre_fault_memory() -- pre-fault and link gmap dat tables
+ * @vcpu: the vcpu that shall appear to have generated the fault-in.
+ * @range: the range that needs to be faulted in.
+ *
+ * The first page of the given range is faulted in and the corresponding gmap
+ * page tables are created, as if the given vCPU had performed a read
+ * operation.
+ * If the range starts outside any memslots, an error is returned. An error is
+ * also returned for UCONTROL VMs, which should instead use the
+ * KVM_S390_VCPU_FAULT ioctl.
+ *
+ * Return:
+ * * %-ENOENT if the range lies outside of a memslot.
+ * * %-EINVAL in case of invalid state (for example if the VM is UCONTROL).
+ * * %-EIO if errors happen while faulting-in the page (will trigger a warning
+ * in the caller).
+ * * other error codes < 0 in case of other errors.
+ * * otherwise a number > 0 of bytes that have been faulted in successfully.
+ */
+long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, struct kvm_pre_fault_memory *range)
+{
+ struct guest_fault f = { .gfn = gpa_to_gfn(range->gpa), };
+ gpa_t end;
+ int rc;
+
+ if (kvm_is_ucontrol(vcpu->kvm))
+ return -EINVAL;
+
+ rc = kvm_s390_faultin_gfn(vcpu, NULL, &f);
+ if (rc == PGM_ADDRESSING)
+ return -ENOENT;
+ if (rc > 0)
+ return -EIO;
+ if (rc < 0)
+ return rc;
+
+ if (f.ptep)
+ return PAGE_SIZE;
+
+ end = ALIGN(range->gpa + PAGE_SIZE, f.crste_region3 ? _REGION3_SIZE : HPAGE_SIZE);
+ return min(range->size, end - range->gpa);
+}
+
+/**
* kvm_test_age_gfn() - test young
* @kvm: the kvm instance
* @range: the range of guest addresses whose young status needs to be cleared