diff mbox

[v3,1/1] kvm: Make VM ioctl do a vzalloc instead of a kzalloc

Message ID 20180507221846.168814-1-marcorr@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marc Orr May 7, 2018, 10:18 p.m. UTC
The kvm struct is (currently) tens of kilo-bytes, which turns out to be a
large amount of memory to allocate contiguously via kzalloc. Thus, this
patch changes the kzalloc to a vzalloc, so that the memory allocation is
less likely to fail in resource-constrained environments.

Signed-off-by: Marc Orr <marcorr@google.com>
---
 arch/arm/include/asm/kvm_host.h   |  4 ++++
 arch/arm/kvm/guest.c              | 10 ++++++++++
 arch/arm64/include/asm/kvm_host.h |  4 ++++
 arch/arm64/kvm/guest.c            | 10 ++++++++++
 arch/x86/kvm/svm.c                |  4 ++--
 arch/x86/kvm/vmx.c                |  4 ++--
 include/linux/kvm_host.h          |  5 +++--
 7 files changed, 35 insertions(+), 6 deletions(-)

Comments

Paul Mackerras May 8, 2018, 5:14 a.m. UTC | #1
On Mon, May 07, 2018 at 03:18:46PM -0700, Marc Orr wrote:
> The kvm struct is (currently) tens of kilo-bytes, which turns out to be a
> large amount of memory to allocate contiguously via kzalloc. Thus, this
> patch changes the kzalloc to a vzalloc, so that the memory allocation is
> less likely to fail in resource-constrained environments.

This will break HV KVM on powerpc, which needs the KVM struct to be
physically contiguous and in the linear mapping.  We'll need to add
#define __KVM_HAVE_ARCH_VM_ALLOC to arch/powerpc/include/asm/kvm_host.h
and the kzalloc/kfree variant to arch/powerpc/kvm/powerpc.c much like
you did on arm.

Paul.
Christian Borntraeger May 8, 2018, 5:16 a.m. UTC | #2
On 05/08/2018 07:14 AM, Paul Mackerras wrote:
> On Mon, May 07, 2018 at 03:18:46PM -0700, Marc Orr wrote:
>> The kvm struct is (currently) tens of kilo-bytes, which turns out to be a
>> large amount of memory to allocate contiguously via kzalloc. Thus, this
>> patch changes the kzalloc to a vzalloc, so that the memory allocation is
>> less likely to fail in resource-constrained environments.
> 
> This will break HV KVM on powerpc, which needs the KVM struct to be
> physically contiguous and in the linear mapping.  We'll need to add
> #define __KVM_HAVE_ARCH_VM_ALLOC to arch/powerpc/include/asm/kvm_host.h
> and the kzalloc/kfree variant to arch/powerpc/kvm/powerpc.c much like
> you did on arm.

In the end I also want kmalloc for s390 (since we do not need the vmalloc for
s390 as we are < 16kb).

So Paolo,
can we turn things around and only use vmalloc for x86?
Paolo Bonzini May 8, 2018, 2:56 p.m. UTC | #3
On 08/05/2018 07:16, Christian Borntraeger wrote:
> On 05/08/2018 07:14 AM, Paul Mackerras wrote:
>> On Mon, May 07, 2018 at 03:18:46PM -0700, Marc Orr wrote:
>>> The kvm struct is (currently) tens of kilo-bytes, which turns out to be a
>>> large amount of memory to allocate contiguously via kzalloc. Thus, this
>>> patch changes the kzalloc to a vzalloc, so that the memory allocation is
>>> less likely to fail in resource-constrained environments.
>>
>> This will break HV KVM on powerpc, which needs the KVM struct to be
>> physically contiguous and in the linear mapping.  We'll need to add
>> #define __KVM_HAVE_ARCH_VM_ALLOC to arch/powerpc/include/asm/kvm_host.h
>> and the kzalloc/kfree variant to arch/powerpc/kvm/powerpc.c much like
>> you did on arm.
> 
> In the end I also want kmalloc for s390 (since we do not need the vmalloc for
> s390 as we are < 16kb).
> 
> So Paolo,
> can we turn things around and only use vmalloc for x86?
> 

The other idea that the #define would pick kzalloc vs. vzalloc (instead
of enabling a custom kvm_arch_alloc_vm) would be even better I think.

Paolo
diff mbox

Patch

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index c6a749568dd6..b6b1bdafd08e 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -315,4 +315,8 @@  static inline bool kvm_arm_harden_branch_predictor(void)
 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__ */
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 1e0784ebbfd6..20990b22e593 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -41,6 +41,16 @@  struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
+struct kvm *kvm_arch_alloc_vm(void)
+{
+	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+}
+
+void kvm_arch_free_vm(struct kvm *kvm)
+{
+	kfree(kvm);
+}
+
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	return 0;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ab46bc70add6..51a64ff6965e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -452,4 +452,8 @@  static inline bool kvm_arm_harden_branch_predictor(void)
 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__ */
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 959e50d2588c..4dd0549a41d3 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -46,6 +46,16 @@  struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
+struct kvm *kvm_arch_alloc_vm(void)
+{
+	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+}
+
+void kvm_arch_free_vm(struct kvm *kvm)
+{
+	kfree(kvm);
+}
+
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	return 0;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index b58787daf9f8..f990fda1b2f6 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1838,13 +1838,13 @@  static void __unregister_enc_region_locked(struct kvm *kvm,
 
 static struct kvm *svm_vm_alloc(void)
 {
-	struct kvm_svm *kvm_svm = kzalloc(sizeof(struct kvm_svm), GFP_KERNEL);
+	struct kvm_svm *kvm_svm = vzalloc(sizeof(struct kvm_svm));
 	return &kvm_svm->kvm;
 }
 
 static void svm_vm_free(struct kvm *kvm)
 {
-	kfree(to_kvm_svm(kvm));
+	vfree(to_kvm_svm(kvm));
 }
 
 static void sev_vm_destroy(struct kvm *kvm)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index aafcc9881e88..26ab153a293f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -9949,13 +9949,13 @@  STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
 
 static struct kvm *vmx_vm_alloc(void)
 {
-	struct kvm_vmx *kvm_vmx = kzalloc(sizeof(struct kvm_vmx), GFP_KERNEL);
+	struct kvm_vmx *kvm_vmx = vzalloc(sizeof(struct kvm_vmx));
 	return &kvm_vmx->kvm;
 }
 
 static void vmx_vm_free(struct kvm *kvm)
 {
-	kfree(to_kvm_vmx(kvm));
+	vfree(to_kvm_vmx(kvm));
 }
 
 static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 6930c63126c7..cf7b6a3a4197 100644
--- 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>
@@ -810,12 +811,12 @@  int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 static inline struct kvm *kvm_arch_alloc_vm(void)
 {
-	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+	return vzalloc(sizeof(struct kvm));
 }
 
 static inline void kvm_arch_free_vm(struct kvm *kvm)
 {
-	kfree(kvm);
+	vfree(kvm);
 }
 #endif