-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
KVM: x86: hyper-v: Move the remote TLB flush logic out of vmx
Currently the remote TLB flush logic is specific to VMX. Move it to a common place so that SVM can use it as well. Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com> Message-Id: <4f4e4ca19778437dae502f44363a38e99e3ef5d1.1622730232.git.viremana@linux.microsoft.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
- Loading branch information
Vineeth Pillai
authored and
Paolo Bonzini
committed
Jun 17, 2021
1 parent
32431fb
commit 3c86c0d
Showing
7 changed files
with
150 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* | ||
* KVM L1 hypervisor optimizations on Hyper-V. | ||
*/ | ||
|
||
#include <linux/kvm_host.h> | ||
#include <asm/mshyperv.h> | ||
|
||
#include "hyperv.h" | ||
#include "kvm_onhyperv.h" | ||
|
||
static int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush, | ||
void *data) | ||
{ | ||
struct kvm_tlb_range *range = data; | ||
|
||
return hyperv_fill_flush_guest_mapping_list(flush, range->start_gfn, | ||
range->pages); | ||
} | ||
|
||
static inline int hv_remote_flush_root_tdp(hpa_t root_tdp, | ||
struct kvm_tlb_range *range) | ||
{ | ||
if (range) | ||
return hyperv_flush_guest_mapping_range(root_tdp, | ||
kvm_fill_hv_flush_list_func, (void *)range); | ||
else | ||
return hyperv_flush_guest_mapping(root_tdp); | ||
} | ||
|
||
int hv_remote_flush_tlb_with_range(struct kvm *kvm, | ||
struct kvm_tlb_range *range) | ||
{ | ||
struct kvm_arch *kvm_arch = &kvm->arch; | ||
struct kvm_vcpu *vcpu; | ||
int ret = 0, i, nr_unique_valid_roots; | ||
hpa_t root; | ||
|
||
spin_lock(&kvm_arch->hv_root_tdp_lock); | ||
|
||
if (!VALID_PAGE(kvm_arch->hv_root_tdp)) { | ||
nr_unique_valid_roots = 0; | ||
|
||
/* | ||
* Flush all valid roots, and see if all vCPUs have converged | ||
* on a common root, in which case future flushes can skip the | ||
* loop and flush the common root. | ||
*/ | ||
kvm_for_each_vcpu(i, vcpu, kvm) { | ||
root = vcpu->arch.hv_root_tdp; | ||
if (!VALID_PAGE(root) || root == kvm_arch->hv_root_tdp) | ||
continue; | ||
|
||
/* | ||
* Set the tracked root to the first valid root. Keep | ||
* this root for the entirety of the loop even if more | ||
* roots are encountered as a low effort optimization | ||
* to avoid flushing the same (first) root again. | ||
*/ | ||
if (++nr_unique_valid_roots == 1) | ||
kvm_arch->hv_root_tdp = root; | ||
|
||
if (!ret) | ||
ret = hv_remote_flush_root_tdp(root, range); | ||
|
||
/* | ||
* Stop processing roots if a failure occurred and | ||
* multiple valid roots have already been detected. | ||
*/ | ||
if (ret && nr_unique_valid_roots > 1) | ||
break; | ||
} | ||
|
||
/* | ||
* The optimized flush of a single root can't be used if there | ||
* are multiple valid roots (obviously). | ||
*/ | ||
if (nr_unique_valid_roots > 1) | ||
kvm_arch->hv_root_tdp = INVALID_PAGE; | ||
} else { | ||
ret = hv_remote_flush_root_tdp(kvm_arch->hv_root_tdp, range); | ||
} | ||
|
||
spin_unlock(&kvm_arch->hv_root_tdp_lock); | ||
return ret; | ||
} | ||
EXPORT_SYMBOL_GPL(hv_remote_flush_tlb_with_range); | ||
|
||
int hv_remote_flush_tlb(struct kvm *kvm) | ||
{ | ||
return hv_remote_flush_tlb_with_range(kvm, NULL); | ||
} | ||
EXPORT_SYMBOL_GPL(hv_remote_flush_tlb); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
/* | ||
* KVM L1 hypervisor optimizations on Hyper-V. | ||
*/ | ||
|
||
#ifndef __ARCH_X86_KVM_KVM_ONHYPERV_H__ | ||
#define __ARCH_X86_KVM_KVM_ONHYPERV_H__ | ||
|
||
#if IS_ENABLED(CONFIG_HYPERV) | ||
int hv_remote_flush_tlb_with_range(struct kvm *kvm, | ||
struct kvm_tlb_range *range); | ||
int hv_remote_flush_tlb(struct kvm *kvm); | ||
|
||
static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp) | ||
{ | ||
struct kvm_arch *kvm_arch = &vcpu->kvm->arch; | ||
|
||
if (kvm_x86_ops.tlb_remote_flush == hv_remote_flush_tlb) { | ||
spin_lock(&kvm_arch->hv_root_tdp_lock); | ||
vcpu->arch.hv_root_tdp = root_tdp; | ||
if (root_tdp != kvm_arch->hv_root_tdp) | ||
kvm_arch->hv_root_tdp = INVALID_PAGE; | ||
spin_unlock(&kvm_arch->hv_root_tdp_lock); | ||
} | ||
} | ||
#else /* !CONFIG_HYPERV */ | ||
static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp) | ||
{ | ||
} | ||
#endif /* !CONFIG_HYPERV */ | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters