diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2012-12-10 18:33:03 +0100 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-12-14 02:21:53 +0100 |
commit | b7f69c555ca430129b6cde81e9f0927531420c5c (patch) | |
tree | 7b325611705e6293ce1fe3c87eeeb30746e2fe0e | |
parent | KVM: Fix iommu map/unmap to handle memory slot moves (diff) | |
download | linux-b7f69c555ca430129b6cde81e9f0927531420c5c.tar.xz linux-b7f69c555ca430129b6cde81e9f0927531420c5c.zip |
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.c | 21 |
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, unsigned long npages; struct kvm_memory_slot *memslot, *slot; struct kvm_memory_slot old, new; - struct kvm_memslots *slots, *old_memslots; + struct kvm_memslots *slots = NULL, *old_memslots; r = check_memory_region_flags(mem); if (r) @@ -832,18 +832,25 @@ int __kvm_set_memory_region(struct kvm *kvm, * - kvm_is_visible_gfn (mmu_check_roots) */ kvm_arch_flush_shadow_memslot(kvm, slot); - kfree(old_memslots); + slots = old_memslots; } r = kvm_arch_prepare_memory_region(kvm, &new, old, mem, user_alloc); if (r) - goto out_free; + goto out_slots; r = -ENOMEM; - slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), - GFP_KERNEL); - if (!slots) - goto out_free; + /* + * We can re-use the old_memslots from above, the only difference + * from the currently installed memslots is the invalid flag. This + * will get overwritten by update_memslots anyway. + */ + if (!slots) { + slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), + GFP_KERNEL); + if (!slots) + goto out_free; + } /* map new memory slot into the iommu */ if (npages) { |