summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2019-05-24 16:06:23 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-19 08:18:05 +0200
commitf69f5679ff8fa1441754ea5f5b863c1a38bd5e93 (patch)
treec9a681715d8e34f82b1ce9185fcd43261f9d6fcf
parent9d8f338c92cc37de3242149336cc00f1da327b57 (diff)
downloadlinux-rpi3-f69f5679ff8fa1441754ea5f5b863c1a38bd5e93.tar.gz
linux-rpi3-f69f5679ff8fa1441754ea5f5b863c1a38bd5e93.tar.bz2
linux-rpi3-f69f5679ff8fa1441754ea5f5b863c1a38bd5e93.zip
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 <borntraeger@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--arch/s390/kvm/kvm-s390.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index f538e3fac7ad..fc7de27960e7 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -4156,21 +4156,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;