Blob Blame History Raw
From: Marc Orr <marcorr@google.com>
Date: Tue, 15 May 2018 04:37:37 -0700
Subject: kvm: Make VM ioctl do valloc for some archs
Git-commit: d1e5b0e98ea27b4f17871dc4e8ea4b0447e35221
Patch-mainline: v4.18-rc1
References: bsc#1111506

The kvm struct has been bloating. For example, it's tens of kilo-bytes
for x86, which turns out to be a large amount of memory to allocate
contiguously via kzalloc. Thus, this patch does the following:
1. Uses architecture-specific routines to allocate the kvm struct via
   vzalloc for x86.
2. Switches arm to __KVM_HAVE_ARCH_VM_ALLOC so that it can use vzalloc
   when has_vhe() is true.

Other architectures continue to default to kalloc, as they have a
dependency on kalloc or have a small-enough struct kvm.

Signed-off-by: Marc Orr <marcorr@google.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Joerg Roedel <jroedel@suse.de>
---
 arch/arm/include/asm/kvm_host.h   |    4 ++++
 arch/arm64/include/asm/kvm_host.h |    4 ++++
 arch/x86/kvm/svm.c                |    4 ++--
 arch/x86/kvm/vmx.c                |    4 ++--
 include/linux/kvm_host.h          |    5 +++++
 virt/kvm/arm/arm.c                |   15 +++++++++++++++
 6 files changed, 32 insertions(+), 4 deletions(-)

--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -332,4 +332,8 @@ static inline bool kvm_arm_harden_branch
 static inline void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {}
 
+#define __KVM_HAVE_ARCH_VM_ALLOC
+struct kvm *kvm_arch_alloc_vm(void);
+void kvm_arch_free_vm(struct kvm *kvm);
+
 #endif /* __ARM_KVM_HOST_H__ */
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -445,4 +445,8 @@ static inline bool kvm_arm_harden_branch
 void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu);
 void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu);
 
+#define __KVM_HAVE_ARCH_VM_ALLOC
+struct kvm *kvm_arch_alloc_vm(void);
+void kvm_arch_free_vm(struct kvm *kvm);
+
 #endif /* __ARM64_KVM_HOST_H__ */
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1807,12 +1807,12 @@ static void __unregister_enc_region_lock
 
 static struct kvm *svm_vm_alloc(void)
 {
-	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+	return vzalloc(sizeof(struct kvm));
 }
 
 static void svm_vm_free(struct kvm *kvm)
 {
-	kfree(kvm);
+	vfree(kvm);
 }
 
 static void sev_vm_destroy(struct kvm *kvm)
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -9676,12 +9676,12 @@ STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
 
 static struct kvm *vmx_vm_alloc(void)
 {
-	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+	return vzalloc(sizeof(struct kvm));
 }
 
 static void vmx_vm_free(struct kvm *kvm)
 {
-	kfree(kvm);
+	vfree(kvm);
 }
 
 static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -19,6 +19,7 @@
 #include <linux/preempt.h>
 #include <linux/msi.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/rcupdate.h>
 #include <linux/ratelimit.h>
 #include <linux/err.h>
@@ -811,6 +812,10 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
+/*
+ * All architectures that want to use vzalloc currently also
+ * need their own kvm_arch_alloc_vm implementation.
+ */
 static inline struct kvm *kvm_arch_alloc_vm(void)
 {
 	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -249,6 +249,21 @@ long kvm_arch_dev_ioctl(struct file *fil
 	return -EINVAL;
 }
 
+struct kvm *kvm_arch_alloc_vm(void)
+{
+	if (!has_vhe())
+		return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+
+	return vzalloc(sizeof(struct kvm));
+}
+
+void kvm_arch_free_vm(struct kvm *kvm)
+{
+	if (!has_vhe())
+		kfree(kvm);
+	else
+		vfree(kvm);
+}
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {