From: David Woodhouse <[email protected]>

A memslot being deleted or moved is present in the active array but
flagged KVM_MEMSLOT_INVALID — a transient state which exists only
within a single KVM_SET_USER_MEMORY_REGION call and is announced by
a further generation bump when it resolves. gfn_to_hva_memslot()
collapses that case and a genuinely unbacked gfn into one error, and
the pfncache refresh reported both as -EFAULT.

Distinguish them: return -EAGAIN when the slot exists but is
invalid, mirroring what RET_PF_RETRY does for ordinary guest faults
on an invalid slot. Existing users don't *need* to change; most
will simply resolve again at the next refresh. But the distinct
error code *allows* a caller to retry.

Signed-off-by: David Woodhouse <[email protected]>
Assisted-by: LLM
---
 virt/kvm/pfncache.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c
index 3659686b97c2..17aaebd76db8 100644
--- a/virt/kvm/pfncache.c
+++ b/virt/kvm/pfncache.c
@@ -304,7 +304,22 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, 
gpa_t gpa, unsigned l
                        gpc->uhva = gfn_to_hva_memslot(gpc->memslot, gfn);
 
                        if (kvm_is_error_hva(gpc->uhva)) {
-                               ret = -EFAULT;
+                               /*
+                                * A slot being deleted or moved is present
+                                * but flagged invalid; the lookup failure is
+                                * transient, resolved when the update
+                                * completes (or reverts) and announced by a
+                                * new memslot generation. Distinguish that
+                                * from a genuinely unbacked gfn so that the
+                                * caller may retry rather than report an
+                                * error, as RET_PF_RETRY does for ordinary
+                                * guest faults.
+                                */
+                               if (gpc->memslot &&
+                                   (gpc->memslot->flags & KVM_MEMSLOT_INVALID))
+                                       ret = -EAGAIN;
+                               else
+                                       ret = -EFAULT;
                                goto out;
                        }
 
-- 
2.43.0


Reply via email to