KVM: s390: fix memory slot handling for KVM_SET_USER_MEMORY_REGION [Linux 4.14.128]

KVM: s390: fix memory slot handling for KVM_SET_USER_MEMORY_REGION [Linux 4.14.128]

This Linux kernel change "KVM: s390: fix memory slot handling for KVM_SET_USER_MEMORY_REGION" is included in the Linux 4.14.128 release. This change is authored by Christian Borntraeger <borntraeger [at] de.ibm.com> on Fri May 24 16:06:23 2019 +0200. The commit for this change in Linux stable tree is 4739012 (patch) which is from upstream commit 19ec166. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 19ec166.

KVM: s390: fix memory slot handling for KVM_SET_USER_MEMORY_REGION

[ Upstream commit 19ec166c3f39fe1d3789888a74cc95544ac266d4 ]

kselftests exposed a problem in the s390 handling for memory slots.
Right now we only do proper memory slot handling for creation of new
memory slots. Neither MOVE, nor DELETION are handled properly. Let us
implement those.

Signed-off-by: Christian Borntraeger <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>

There are 35 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/s390/kvm/kvm-s390.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index d6fe229..70a446e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3913,21 +3913,28 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                const struct kvm_memory_slot *new,
                enum kvm_mr_change change)
 {
-   int rc;
-
-   /* If the basics of the memslot do not change, we do not want
-    * to update the gmap. Every update causes several unnecessary
-    * segment translation exceptions. This is usually handled just
-    * fine by the normal fault handler + gmap, but it will also
-    * cause faults on the prefix page of running guest CPUs.
-    */
-   if (old->userspace_addr == mem->userspace_addr &&
-       old->base_gfn * PAGE_SIZE == mem->guest_phys_addr &&
-       old->npages * PAGE_SIZE == mem->memory_size)
-       return;
+   int rc = 0;

-   rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
-       mem->guest_phys_addr, mem->memory_size);
+   switch (change) {
+   case KVM_MR_DELETE:
+       rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
+                   old->npages * PAGE_SIZE);
+       break;
+   case KVM_MR_MOVE:
+       rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
+                   old->npages * PAGE_SIZE);
+       if (rc)
+           break;
+       /* FALLTHROUGH */
+   case KVM_MR_CREATE:
+       rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
+                     mem->guest_phys_addr, mem->memory_size);
+       break;
+   case KVM_MR_FLAGS_ONLY:
+       break;
+   default:
+       WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
+   }
    if (rc)
        pr_warn("failed to commit memory region\n");
    return;

Leave a Reply

Your email address will not be published. Required fields are marked *