diff mbox

[v4,1/1] kvm: Make VM ioctl do valloc for some archs

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

Commit Message

Marc Orr May 14, 2018, 7:01 p.m. UTC
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 allocat the kvm struct via
   kzalloc for x86 and also for arm when has_tbe() is true.
2. Introduces a baseline allocator for the kvm struct that uses valloc.
   This allocator can be used by an architecture by defining the
   __KVM_VALLOC_ARCH_VM macro before including include/linux/kvm_host.h.
3. Finally, continue to default to kalloc for all other situations, as
   many architectures have taken a dependence on kalloc.

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

Comments

Marc Zyngier May 15, 2018, 8:44 a.m. UTC | #1
On 14/05/18 20:01, Marc Orr wrote:
> 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 allocat the kvm struct via
>    kzalloc for x86 and also for arm when has_tbe() is true.
> 2. Introduces a baseline allocator for the kvm struct that uses valloc.
>    This allocator can be used by an architecture by defining the
>    __KVM_VALLOC_ARCH_VM macro before including include/linux/kvm_host.h.
> 3. Finally, continue to default to kalloc for all other situations, as
>    many architectures have taken a dependence on kalloc.
> 
> Signed-off-by: Marc Orr <marcorr@google.com>
> Change-Id: Ide392e51991142d1325e06351231ac685e11d820
> ---
>  arch/arm/include/asm/kvm_host.h   |  4 ++++
>  arch/arm/kvm/guest.c              | 16 ++++++++++++++++
>  arch/arm64/include/asm/kvm_host.h |  4 ++++
>  arch/arm64/kvm/guest.c            | 16 ++++++++++++++++
>  arch/x86/kvm/svm.c                |  4 ++--
>  arch/x86/kvm/vmx.c                |  4 ++--
>  include/linux/kvm_host.h          | 13 +++++++++++++
>  7 files changed, 57 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index c7c28c885a19..f38fd60b4d4d 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -318,4 +318,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 a18f33edc471..2b88b745f5a3 100644
> --- a/arch/arm/kvm/guest.c
> +++ b/arch/arm/kvm/guest.c
> @@ -42,6 +42,22 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
>  	{ NULL }
>  };
>  
> +struct kvm *kvm_arch_alloc_vm(void)
> +{
> +	if (!has_vhe())
> +		return kzalloc(sizeof(struct kvm), GFP_KERNEL);
> +
> +	return vzalloc(sizeof(struct kvm));

This doesn't make much sense.

Either you pick the patch I provided which makes the allocation a common
path between arm and arm64 by sticking it in common code (and then the
has_vhe()) test makes sense), or you make it per-architecture, and the
whole has_vhe() for 32bit ARM is just churn (to the point where you
shouldn't define __KVM_HAVE_ARCH_VM_ALLOC at all for that architecture).

Thanks,

	M.
Marc Orr May 15, 2018, 11:22 a.m. UTC | #2
Got it. I'll send another version shortly.
Thanks,
Marc
On Tue, May 15, 2018 at 1:44 AM Marc Zyngier <marc.zyngier@arm.com> wrote:

> On 14/05/18 20:01, Marc Orr wrote:
> > 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 allocat the kvm struct via
> >    kzalloc for x86 and also for arm when has_tbe() is true.
> > 2. Introduces a baseline allocator for the kvm struct that uses valloc.
> >    This allocator can be used by an architecture by defining the
> >    __KVM_VALLOC_ARCH_VM macro before including include/linux/kvm_host.h.
> > 3. Finally, continue to default to kalloc for all other situations, as
> >    many architectures have taken a dependence on kalloc.
> >
> > Signed-off-by: Marc Orr <marcorr@google.com>
> > Change-Id: Ide392e51991142d1325e06351231ac685e11d820
> > ---
> >  arch/arm/include/asm/kvm_host.h   |  4 ++++
> >  arch/arm/kvm/guest.c              | 16 ++++++++++++++++
> >  arch/arm64/include/asm/kvm_host.h |  4 ++++
> >  arch/arm64/kvm/guest.c            | 16 ++++++++++++++++
> >  arch/x86/kvm/svm.c                |  4 ++--
> >  arch/x86/kvm/vmx.c                |  4 ++--
> >  include/linux/kvm_host.h          | 13 +++++++++++++
> >  7 files changed, 57 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/kvm_host.h
b/arch/arm/include/asm/kvm_host.h
> > index c7c28c885a19..f38fd60b4d4d 100644
> > --- a/arch/arm/include/asm/kvm_host.h
> > +++ b/arch/arm/include/asm/kvm_host.h
> > @@ -318,4 +318,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 a18f33edc471..2b88b745f5a3 100644
> > --- a/arch/arm/kvm/guest.c
> > +++ b/arch/arm/kvm/guest.c
> > @@ -42,6 +42,22 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
> >       { NULL }
> >  };
> >
> > +struct kvm *kvm_arch_alloc_vm(void)
> > +{
> > +     if (!has_vhe())
> > +             return kzalloc(sizeof(struct kvm), GFP_KERNEL);
> > +
> > +     return vzalloc(sizeof(struct kvm));

> This doesn't make much sense.

> Either you pick the patch I provided which makes the allocation a common
> path between arm and arm64 by sticking it in common code (and then the
> has_vhe()) test makes sense), or you make it per-architecture, and the
> whole has_vhe() for 32bit ARM is just churn (to the point where you
> shouldn't define __KVM_HAVE_ARCH_VM_ALLOC at all for that architecture).

> Thanks,

>          M.
> --
> Jazz is not dead. It just smells funny...
diff mbox

Patch

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index c7c28c885a19..f38fd60b4d4d 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -318,4 +318,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 a18f33edc471..2b88b745f5a3 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -42,6 +42,22 @@  struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
+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);
+}
+
 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 469de8acd06f..358b1b4dcd92 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -455,4 +455,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 56a0260ceb11..8bc898079167 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -47,6 +47,22 @@  struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
+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);
+}
+
 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 1fc05e428aba..45b903ed3e5d 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1849,13 +1849,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 3f1696570b41..ee85ba887db6 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -9936,13 +9936,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 6d6e79c59e68..e3134283321a 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>
@@ -808,6 +809,17 @@  bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
+#ifdef __KVM_VALLOC_ARCH_VM
+static inline struct kvm *kvm_arch_alloc_vm(void)
+{
+	return vzalloc(sizeof(struct kvm));
+}
+
+static inline void kvm_arch_free_vm(struct kvm *kvm)
+{
+	vfree(kvm);
+}
+#else
 static inline struct kvm *kvm_arch_alloc_vm(void)
 {
 	return kzalloc(sizeof(struct kvm), GFP_KERNEL);
@@ -818,6 +830,7 @@  static inline void kvm_arch_free_vm(struct kvm *kvm)
 	kfree(kvm);
 }
 #endif
+#endif
 
 #ifdef __KVM_HAVE_ARCH_NONCOHERENT_DMA
 void kvm_arch_register_noncoherent_dma(struct kvm *kvm);