Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: X86: Dynamically allocate user_fpu

After reverting commit 240c35a3783a (kvm: x86: Use task structs fpu field
for user), struct kvm_vcpu is 19456 bytes on my server, PAGE_ALLOC_COSTLY_ORDER(3)
is the order at which allocations are deemed costly to service. In serveless
scenario, one host can service hundreds/thoudands firecracker/kata-container
instances, howerver, new instance will fail to launch after memory is too
fragmented to allocate kvm_vcpu struct on host, this was observed in some
cloud provider product environments.

This patch dynamically allocates user_fpu, kvm_vcpu is 15168 bytes now on my
Skylake server.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Wanpeng Li and committed by
Paolo Bonzini
d9a710e5 e7517324

+27 -5
+1 -1
arch/x86/include/asm/kvm_host.h
··· 616 616 * "guest_fpu" state here contains the guest FPU context, with the 617 617 * host PRKU bits. 618 618 */ 619 - struct fpu user_fpu; 619 + struct fpu *user_fpu; 620 620 struct fpu *guest_fpu; 621 621 622 622 u64 xcr0;
+12 -1
arch/x86/kvm/svm.c
··· 2143 2143 goto out; 2144 2144 } 2145 2145 2146 + svm->vcpu.arch.user_fpu = kmem_cache_zalloc(x86_fpu_cache, 2147 + GFP_KERNEL_ACCOUNT); 2148 + if (!svm->vcpu.arch.user_fpu) { 2149 + printk(KERN_ERR "kvm: failed to allocate kvm userspace's fpu\n"); 2150 + err = -ENOMEM; 2151 + goto free_partial_svm; 2152 + } 2153 + 2146 2154 svm->vcpu.arch.guest_fpu = kmem_cache_zalloc(x86_fpu_cache, 2147 2155 GFP_KERNEL_ACCOUNT); 2148 2156 if (!svm->vcpu.arch.guest_fpu) { 2149 2157 printk(KERN_ERR "kvm: failed to allocate vcpu's fpu\n"); 2150 2158 err = -ENOMEM; 2151 - goto free_partial_svm; 2159 + goto free_user_fpu; 2152 2160 } 2153 2161 2154 2162 err = kvm_vcpu_init(&svm->vcpu, kvm, id); ··· 2219 2211 kvm_vcpu_uninit(&svm->vcpu); 2220 2212 free_svm: 2221 2213 kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.guest_fpu); 2214 + free_user_fpu: 2215 + kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.user_fpu); 2222 2216 free_partial_svm: 2223 2217 kmem_cache_free(kvm_vcpu_cache, svm); 2224 2218 out: ··· 2251 2241 __free_page(virt_to_page(svm->nested.hsave)); 2252 2242 __free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER); 2253 2243 kvm_vcpu_uninit(vcpu); 2244 + kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.user_fpu); 2254 2245 kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.guest_fpu); 2255 2246 kmem_cache_free(kvm_vcpu_cache, svm); 2256 2247 }
+12 -1
arch/x86/kvm/vmx/vmx.c
··· 6598 6598 free_loaded_vmcs(vmx->loaded_vmcs); 6599 6599 kfree(vmx->guest_msrs); 6600 6600 kvm_vcpu_uninit(vcpu); 6601 + kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.user_fpu); 6601 6602 kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.guest_fpu); 6602 6603 kmem_cache_free(kvm_vcpu_cache, vmx); 6603 6604 } ··· 6614 6613 if (!vmx) 6615 6614 return ERR_PTR(-ENOMEM); 6616 6615 6616 + vmx->vcpu.arch.user_fpu = kmem_cache_zalloc(x86_fpu_cache, 6617 + GFP_KERNEL_ACCOUNT); 6618 + if (!vmx->vcpu.arch.user_fpu) { 6619 + printk(KERN_ERR "kvm: failed to allocate kvm userspace's fpu\n"); 6620 + err = -ENOMEM; 6621 + goto free_partial_vcpu; 6622 + } 6623 + 6617 6624 vmx->vcpu.arch.guest_fpu = kmem_cache_zalloc(x86_fpu_cache, 6618 6625 GFP_KERNEL_ACCOUNT); 6619 6626 if (!vmx->vcpu.arch.guest_fpu) { 6620 6627 printk(KERN_ERR "kvm: failed to allocate vcpu's fpu\n"); 6621 6628 err = -ENOMEM; 6622 - goto free_partial_vcpu; 6629 + goto free_user_fpu; 6623 6630 } 6624 6631 6625 6632 vmx->vpid = allocate_vpid(); ··· 6730 6721 free_vcpu: 6731 6722 free_vpid(vmx->vpid); 6732 6723 kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.guest_fpu); 6724 + free_user_fpu: 6725 + kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.user_fpu); 6733 6726 free_partial_vcpu: 6734 6727 kmem_cache_free(kvm_vcpu_cache, vmx); 6735 6728 return ERR_PTR(err);
+2 -2
arch/x86/kvm/x86.c
··· 8273 8273 { 8274 8274 fpregs_lock(); 8275 8275 8276 - copy_fpregs_to_fpstate(&vcpu->arch.user_fpu); 8276 + copy_fpregs_to_fpstate(vcpu->arch.user_fpu); 8277 8277 /* PKRU is separately restored in kvm_x86_ops->run. */ 8278 8278 __copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state, 8279 8279 ~XFEATURE_MASK_PKRU); ··· 8290 8290 fpregs_lock(); 8291 8291 8292 8292 copy_fpregs_to_fpstate(vcpu->arch.guest_fpu); 8293 - copy_kernel_to_fpregs(&vcpu->arch.user_fpu.state); 8293 + copy_kernel_to_fpregs(&vcpu->arch.user_fpu->state); 8294 8294 8295 8295 fpregs_mark_activate(); 8296 8296 fpregs_unlock();