]> git.itanic.dy.fi Git - linux-stable/commitdiff
KVM: x86: Move Hyper-V partition assist page out of Hyper-V emulation context
authorVitaly Kuznetsov <vkuznets@redhat.com>
Tue, 5 Dec 2023 10:36:16 +0000 (11:36 +0100)
committerSean Christopherson <seanjc@google.com>
Thu, 7 Dec 2023 17:34:01 +0000 (09:34 -0800)
Hyper-V partition assist page is used when KVM runs on top of Hyper-V and
is not used for Windows/Hyper-V guests on KVM, this means that 'hv_pa_pg'
placement in 'struct kvm_hv' is unfortunate. As a preparation to making
Hyper-V emulation optional, move 'hv_pa_pg' to 'struct kvm_arch' and put it
under CONFIG_HYPERV.

While on it, introduce hv_get_partition_assist_page() helper to allocate
partition assist page. Move the comment explaining why we use a single page
for all vCPUs from VMX and expand it a bit.

No functional change intended.

Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Tested-by: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Link: https://lore.kernel.org/r/20231205103630.1391318-3-vkuznets@redhat.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/kvm_onhyperv.h
arch/x86/kvm/svm/svm_onhyperv.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c

index b0ca65632f2cea66b57ea09da9cd8307bbbdaac6..86069b985d227f923b5e4155fac326cbf91ee2a5 100644 (file)
@@ -1125,7 +1125,6 @@ struct kvm_hv {
         */
        unsigned int synic_auto_eoi_used;
 
-       struct hv_partition_assist_pg *hv_pa_pg;
        struct kvm_hv_syndbg hv_syndbg;
 };
 
@@ -1447,6 +1446,7 @@ struct kvm_arch {
 #if IS_ENABLED(CONFIG_HYPERV)
        hpa_t   hv_root_tdp;
        spinlock_t hv_root_tdp_lock;
+       struct hv_partition_assist_pg *hv_pa_pg;
 #endif
        /*
         * VM-scope maximum vCPU ID. Used to determine the size of structures
index f9ca3e7432b2e8fc983dd61bbc2887e38f4a93a2..eefab3dc8498b79cb083b827ec8c415315aaae14 100644 (file)
 int hv_flush_remote_tlbs_range(struct kvm *kvm, gfn_t gfn, gfn_t nr_pages);
 int hv_flush_remote_tlbs(struct kvm *kvm);
 void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
+static inline hpa_t hv_get_partition_assist_page(struct kvm_vcpu *vcpu)
+{
+       /*
+        * Partition assist page is something which Hyper-V running in L0
+        * requires from KVM running in L1 before direct TLB flush for L2
+        * guests can be enabled. KVM doesn't currently use the page but to
+        * comply with TLFS it still needs to be allocated. For now, this
+        * is a single page shared among all vCPUs.
+        */
+       struct hv_partition_assist_pg **p_hv_pa_pg =
+               &vcpu->kvm->arch.hv_pa_pg;
+
+       if (!*p_hv_pa_pg)
+               *p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL_ACCOUNT);
+
+       if (!*p_hv_pa_pg)
+               return INVALID_PAGE;
+
+       return __pa(*p_hv_pa_pg);
+}
 #else /* !CONFIG_HYPERV */
 static inline int hv_flush_remote_tlbs(struct kvm *kvm)
 {
index 7af8422d3382101321cc88c4402dbfa83cb24990..3971b3ea5d04b31daa2079156fcf8873b6cc487a 100644 (file)
 int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
 {
        struct hv_vmcb_enlightenments *hve;
-       struct hv_partition_assist_pg **p_hv_pa_pg =
-                       &to_kvm_hv(vcpu->kvm)->hv_pa_pg;
+       hpa_t partition_assist_page = hv_get_partition_assist_page(vcpu);
 
-       if (!*p_hv_pa_pg)
-               *p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL);
-
-       if (!*p_hv_pa_pg)
+       if (partition_assist_page == INVALID_PAGE)
                return -ENOMEM;
 
        hve = &to_svm(vcpu)->vmcb->control.hv_enlightenments;
 
-       hve->partition_assist_page = __pa(*p_hv_pa_pg);
+       hve->partition_assist_page = partition_assist_page;
        hve->hv_vm_id = (unsigned long)vcpu->kvm;
        if (!hve->hv_enlightenments_control.nested_flush_hypercall) {
                hve->hv_enlightenments_control.nested_flush_hypercall = 1;
index 40e3780d73aeb2ee24096558a3dcbc8354157b6a..cf19a334663968d2d24a779336798d86efc67b99 100644 (file)
@@ -523,22 +523,14 @@ module_param(enlightened_vmcs, bool, 0444);
 static int hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
 {
        struct hv_enlightened_vmcs *evmcs;
-       struct hv_partition_assist_pg **p_hv_pa_pg =
-                       &to_kvm_hv(vcpu->kvm)->hv_pa_pg;
-       /*
-        * Synthetic VM-Exit is not enabled in current code and so All
-        * evmcs in singe VM shares same assist page.
-        */
-       if (!*p_hv_pa_pg)
-               *p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL_ACCOUNT);
+       hpa_t partition_assist_page = hv_get_partition_assist_page(vcpu);
 
-       if (!*p_hv_pa_pg)
+       if (partition_assist_page == INVALID_PAGE)
                return -ENOMEM;
 
        evmcs = (struct hv_enlightened_vmcs *)to_vmx(vcpu)->loaded_vmcs->vmcs;
 
-       evmcs->partition_assist_page =
-               __pa(*p_hv_pa_pg);
+       evmcs->partition_assist_page = partition_assist_page;
        evmcs->hv_vm_id = (unsigned long)vcpu->kvm;
        evmcs->hv_enlightenments_control.nested_flush_hypercall = 1;
 
index 6d0772b47041345119d0b69dbecaa952de0eb3fe..81224b9676d9920cba777a007dc10baed0285a92 100644 (file)
@@ -12438,7 +12438,9 @@ void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu)
 
 void kvm_arch_free_vm(struct kvm *kvm)
 {
-       kfree(to_kvm_hv(kvm)->hv_pa_pg);
+#if IS_ENABLED(CONFIG_HYPERV)
+       kfree(kvm->arch.hv_pa_pg);
+#endif
        __kvm_arch_free_vm(kvm);
 }