|
|
@@ -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;
|