aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-12-10 12:33:03 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2012-12-13 20:21:53 -0500
commitb7f69c555ca430129b6cde81e9f0927531420c5c (patch)
tree7b325611705e6293ce1fe3c87eeeb30746e2fe0e
parente40f193f5bb022e927a57a4f5d5194e4f12ddb74 (diff)
KVM: Minor memory slot optimization
If a slot is removed or moved in the guest physical address space, we first allocate and install a new slot array with the invalidated entry. The old array is then freed. We then proceed to allocate yet another slot array to install the permanent replacement. Re-use the original array when this occurs and avoid the extra kfree/kmalloc. Reviewed-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--virt/kvm/kvm_main.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 9a56ca2fa257..4c8c0657e370 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -716,7 +716,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
716 unsigned long npages; 716 unsigned long npages;
717 struct kvm_memory_slot *memslot, *slot; 717 struct kvm_memory_slot *memslot, *slot;
718 struct kvm_memory_slot old, new; 718 struct kvm_memory_slot old, new;
719 struct kvm_memslots *slots, *old_memslots; 719 struct kvm_memslots *slots = NULL, *old_memslots;
720 720
721 r = check_memory_region_flags(mem); 721 r = check_memory_region_flags(mem);
722 if (r) 722 if (r)
@@ -832,18 +832,25 @@ int __kvm_set_memory_region(struct kvm *kvm,
832 * - kvm_is_visible_gfn (mmu_check_roots) 832 * - kvm_is_visible_gfn (mmu_check_roots)
833 */ 833 */
834 kvm_arch_flush_shadow_memslot(kvm, slot); 834 kvm_arch_flush_shadow_memslot(kvm, slot);
835 kfree(old_memslots); 835 slots = old_memslots;
836 } 836 }
837 837
838 r = kvm_arch_prepare_memory_region(kvm, &new, old, mem, user_alloc); 838 r = kvm_arch_prepare_memory_region(kvm, &new, old, mem, user_alloc);
839 if (r) 839 if (r)
840 goto out_free; 840 goto out_slots;
841 841
842 r = -ENOMEM; 842 r = -ENOMEM;
843 slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), 843 /*
844 GFP_KERNEL); 844 * We can re-use the old_memslots from above, the only difference
845 if (!slots) 845 * from the currently installed memslots is the invalid flag. This
846 goto out_free; 846 * will get overwritten by update_memslots anyway.
847 */
848 if (!slots) {
849 slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),
850 GFP_KERNEL);
851 if (!slots)
852 goto out_free;
853 }
847 854
848 /* map new memory slot into the iommu */ 855 /* map new memory slot into the iommu */
849 if (npages) { 856 if (npages) {