diff options
| author | Mark Brown <broonie@kernel.org> | 2026-05-29 22:46:50 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-05-29 22:46:50 +0100 |
| commit | 29fa9b4922922bd33cac81162dbf669bfb55a52d (patch) | |
| tree | 1b69a4af640a25f012bab6652dee05ab1878f0d3 /arch | |
| parent | 0ce0f7ee41c6e99f682a62e1d1363881fa18ff58 (diff) | |
| parent | 68f8c9565c4391343aa3b77f7af642a366991405 (diff) | |
| download | linux-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/Kconfig | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/dat.h | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/gmap.c | 2 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 45 |
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 |
