Commit c1a7b32a authored by Takuya Yoshikawa's avatar Takuya Yoshikawa Committed by Avi Kivity

KVM: Avoid wasting pages for small lpage_info arrays

lpage_info is created for each large level even when the memory slot is
not for RAM.  This means that when we add one slot for a PCI device, we
end up allocating at least KVM_NR_PAGE_SIZES - 1 pages by vmalloc().

To make things worse, there is an increasing number of devices which
would result in more pages being wasted this way.

This patch mitigates this problem by using kvm_kvzalloc().
Signed-off-by: default avatarTakuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 92eca8fa
...@@ -6304,7 +6304,7 @@ void kvm_arch_free_memslot(struct kvm_memory_slot *free, ...@@ -6304,7 +6304,7 @@ void kvm_arch_free_memslot(struct kvm_memory_slot *free,
for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
if (!dont || free->arch.lpage_info[i] != dont->arch.lpage_info[i]) { if (!dont || free->arch.lpage_info[i] != dont->arch.lpage_info[i]) {
vfree(free->arch.lpage_info[i]); kvm_kvfree(free->arch.lpage_info[i]);
free->arch.lpage_info[i] = NULL; free->arch.lpage_info[i] = NULL;
} }
} }
...@@ -6323,7 +6323,7 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages) ...@@ -6323,7 +6323,7 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
slot->base_gfn, level) + 1; slot->base_gfn, level) + 1;
slot->arch.lpage_info[i] = slot->arch.lpage_info[i] =
vzalloc(lpages * sizeof(*slot->arch.lpage_info[i])); kvm_kvzalloc(lpages * sizeof(*slot->arch.lpage_info[i]));
if (!slot->arch.lpage_info[i]) if (!slot->arch.lpage_info[i])
goto out_free; goto out_free;
......
...@@ -535,6 +535,9 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu); ...@@ -535,6 +535,9 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
void kvm_free_physmem(struct kvm *kvm); void kvm_free_physmem(struct kvm *kvm);
void *kvm_kvzalloc(unsigned long size);
void kvm_kvfree(const void *addr);
#ifndef __KVM_HAVE_ARCH_VM_ALLOC #ifndef __KVM_HAVE_ARCH_VM_ALLOC
static inline struct kvm *kvm_arch_alloc_vm(void) static inline struct kvm *kvm_arch_alloc_vm(void)
{ {
......
...@@ -520,7 +520,7 @@ static struct kvm *kvm_create_vm(unsigned long type) ...@@ -520,7 +520,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
* Avoid using vmalloc for a small buffer. * Avoid using vmalloc for a small buffer.
* Should not be used when the size is statically known. * Should not be used when the size is statically known.
*/ */
static void *kvm_kvzalloc(unsigned long size) void *kvm_kvzalloc(unsigned long size)
{ {
if (size > PAGE_SIZE) if (size > PAGE_SIZE)
return vzalloc(size); return vzalloc(size);
...@@ -528,7 +528,7 @@ static void *kvm_kvzalloc(unsigned long size) ...@@ -528,7 +528,7 @@ static void *kvm_kvzalloc(unsigned long size)
return kzalloc(size, GFP_KERNEL); return kzalloc(size, GFP_KERNEL);
} }
static void kvm_kvfree(const void *addr) void kvm_kvfree(const void *addr)
{ {
if (is_vmalloc_addr(addr)) if (is_vmalloc_addr(addr))
vfree(addr); vfree(addr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment