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

KVM: x86: hyper-v: Allocate 'struct kvm_vcpu_hv' dynamically

Hyper-V context is only needed for guests which use Hyper-V emulation in
KVM (e.g. Windows/Hyper-V guests). 'struct kvm_vcpu_hv' is, however, quite
big, it accounts for more than 1/4 of the total 'struct kvm_vcpu_arch'
which is also quite big already. This all looks like a waste.

Allocate 'struct kvm_vcpu_hv' dynamically. This patch does not bring any
(intentional) functional change as we still allocate the context
unconditionally but it paves the way to doing that only when needed.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20210126134816.1880136-13-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Vitaly Kuznetsov and committed by
Paolo Bonzini
4592b7ea f2bc14b6

+27 -12
+2 -1
arch/x86/include/asm/kvm_host.h
··· 519 519 520 520 /* Hyper-V per vcpu emulation context */ 521 521 struct kvm_vcpu_hv { 522 + struct kvm_vcpu *vcpu; 522 523 u32 vp_index; 523 524 u64 hv_vapic; 524 525 s64 runtime_offset; ··· 736 735 /* used for guest single stepping over the given code position */ 737 736 unsigned long singlestep_rip; 738 737 739 - struct kvm_vcpu_hv hyperv; 738 + struct kvm_vcpu_hv *hyperv; 740 739 struct kvm_vcpu_xen xen; 741 740 742 741 cpumask_var_t wbinvd_dirty_mask;
+14 -2
arch/x86/kvm/hyperv.c
··· 837 837 838 838 for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) 839 839 stimer_cleanup(&hv_vcpu->stimer[i]); 840 + 841 + kfree(hv_vcpu); 842 + vcpu->arch.hyperv = NULL; 840 843 } 841 844 842 845 bool kvm_hv_assist_page_enabled(struct kvm_vcpu *vcpu) ··· 889 886 stimer_prepare_msg(stimer); 890 887 } 891 888 892 - void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) 889 + int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) 893 890 { 894 - struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); 891 + struct kvm_vcpu_hv *hv_vcpu; 895 892 int i; 893 + 894 + hv_vcpu = kzalloc(sizeof(struct kvm_vcpu_hv), GFP_KERNEL_ACCOUNT); 895 + if (!hv_vcpu) 896 + return -ENOMEM; 897 + 898 + vcpu->arch.hyperv = hv_vcpu; 899 + hv_vcpu->vcpu = vcpu; 896 900 897 901 synic_init(&hv_vcpu->synic); 898 902 899 903 bitmap_zero(hv_vcpu->stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT); 900 904 for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) 901 905 stimer_init(&hv_vcpu->stimer[i], i); 906 + 907 + return 0; 902 908 } 903 909 904 910 void kvm_hv_vcpu_postcreate(struct kvm_vcpu *vcpu)
+6 -7
arch/x86/kvm/hyperv.h
··· 57 57 58 58 static inline struct kvm_vcpu_hv *to_hv_vcpu(struct kvm_vcpu *vcpu) 59 59 { 60 - return &vcpu->arch.hyperv; 60 + return vcpu->arch.hyperv; 61 61 } 62 62 63 63 static inline struct kvm_vcpu *hv_vcpu_to_vcpu(struct kvm_vcpu_hv *hv_vcpu) 64 64 { 65 - struct kvm_vcpu_arch *arch; 66 - 67 - arch = container_of(hv_vcpu, struct kvm_vcpu_arch, hyperv); 68 - return container_of(arch, struct kvm_vcpu, arch); 65 + return hv_vcpu->vcpu; 69 66 } 70 67 71 68 static inline struct kvm_vcpu_hv_synic *to_hv_synic(struct kvm_vcpu *vcpu) 72 69 { 73 - return &vcpu->arch.hyperv.synic; 70 + struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); 71 + 72 + return &hv_vcpu->synic; 74 73 } 75 74 76 75 static inline struct kvm_vcpu *hv_synic_to_vcpu(struct kvm_vcpu_hv_synic *synic) ··· 100 101 void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector); 101 102 int kvm_hv_activate_synic(struct kvm_vcpu *vcpu, bool dont_zero_synic_pages); 102 103 103 - void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); 104 + int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); 104 105 void kvm_hv_vcpu_postcreate(struct kvm_vcpu *vcpu); 105 106 void kvm_hv_vcpu_uninit(struct kvm_vcpu *vcpu); 106 107
+5 -2
arch/x86/kvm/x86.c
··· 10083 10083 vcpu->arch.pending_external_vector = -1; 10084 10084 vcpu->arch.preempted_in_kernel = false; 10085 10085 10086 - kvm_hv_vcpu_init(vcpu); 10086 + if (kvm_hv_vcpu_init(vcpu)) 10087 + goto free_guest_fpu; 10087 10088 10088 10089 r = static_call(kvm_x86_vcpu_create)(vcpu); 10089 10090 if (r) 10090 - goto free_guest_fpu; 10091 + goto free_hv_vcpu; 10091 10092 10092 10093 vcpu->arch.arch_capabilities = kvm_get_arch_capabilities(); 10093 10094 vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT; ··· 10099 10098 vcpu_put(vcpu); 10100 10099 return 0; 10101 10100 10101 + free_hv_vcpu: 10102 + kvm_hv_vcpu_uninit(vcpu); 10102 10103 free_guest_fpu: 10103 10104 kvm_free_guest_fpu(vcpu); 10104 10105 free_user_fpu: