diff options
| author | Claudio Imbrenda <imbrenda@linux.ibm.com> | 2026-08-28 13:54:34 +0200 |
|---|---|---|
| committer | Claudio Imbrenda <imbrenda@linux.ibm.com> | 2026-09-01 15:42:27 +0200 |
| commit | faff4c8ff3dbec6d71b89dd281a0d17c4478fa44 (patch) | |
| tree | 75e52b165b83f652311f80ed72fb6d78d1529eb8 | |
| parent | ae12d2f9c119639a142d92c4a37c30277e8576da (diff) | |
| download | linux-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.c | 13 |
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; |
