summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Imbrenda <imbrenda@linux.ibm.com>2026-08-28 13:54:34 +0200
committerClaudio Imbrenda <imbrenda@linux.ibm.com>2026-09-01 15:42:27 +0200
commitfaff4c8ff3dbec6d71b89dd281a0d17c4478fa44 (patch)
tree75e52b165b83f652311f80ed72fb6d78d1529eb8
parentae12d2f9c119639a142d92c4a37c30277e8576da (diff)
downloadlinux-next-faff4c8ff3dbec6d71b89dd281a0d17c4478fa44.tar.gz
linux-next-faff4c8ff3dbec6d71b89dd281a0d17c4478fa44.zip
KVM: s390: Fix _gaccess_shadow_fault()
In some circumstances, it is possible that the page of nested guest memory that is being shadowed is not present at all in the parent guest gmap. dat_entry_walk() will not find any leaf entry and return with -ENOENT, which will erroneously be propagated all the way to userspace. Fix by manually calling gmap_link() on the memory of the nested guest that is being shadowed if the mapping was not already present. Fixes: e38c884df921 ("KVM: s390: Switch to new gmap") Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Message-ID: <20260828115439.145885-4-imbrenda@linux.ibm.com>
-rw-r--r--arch/s390/kvm/s390/gaccess.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/s390/kvm/s390/gaccess.c b/arch/s390/kvm/s390/gaccess.c
index e5c064f263df..405345ccc4f1 100644
--- a/arch/s390/kvm/s390/gaccess.c
+++ b/arch/s390/kvm/s390/gaccess.c
@@ -1589,12 +1589,25 @@ static inline int ___gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg
parent = READ_ONCE(sg->parent);
if (!parent)
return -EAGAIN;
+retry:
scoped_guard(spinlock, &parent->children_lock) {
if (READ_ONCE(sg->parent) != parent)
return -EAGAIN;
sg->invalidated = false;
rc = _gaccess_do_shadow(vcpu->arch.mc, sg, saddr, walk);
}
+ if (rc == -ENOENT) {
+ struct kvm_memory_slot *slot;
+ struct guest_fault *entries;
+
+ entries = get_entries(walk);
+ slot = kvm_vcpu_gfn_to_memslot(vcpu, entries[LEVEL_MEM].gfn);
+ if (!slot)
+ return PGM_ADDRESSING;
+ rc = gmap_link(vcpu->arch.mc, parent, entries + LEVEL_MEM, slot);
+ if (!rc)
+ goto retry;
+ }
if (!rc)
kvm_s390_release_faultin_array(vcpu->kvm, walk->raw_entries, false);
return rc;