From: Marc Orr 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 Reviewed-by: Marc Zyngier Signed-off-by: Paolo Bonzini Acked-by: Joerg Roedel --- 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 #include #include +#include #include #include #include @@ -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) {