Skip to content

Commit 807b758

Browse files
committed
Merge tag 'kvm-x86-mmu-6.4' of https://github.com/kvm-x86/linux into HEAD
KVM x86 MMU changes for 6.4: - Tweak FNAME(sync_spte) to avoid unnecessary writes+flushes when the guest is only adding new PTEs - Overhaul .sync_page() and .invlpg() to share the .sync_page() implementation, i.e. utilize .sync_page()'s optimizations when emulating invalidations - Clean up the range-based flushing APIs - Revamp the TDP MMU's reaping of Accessed/Dirty bits to clear a single A/D bit using a LOCK AND instead of XCHG, and skip all of the "handle changed SPTE" overhead associated with writing the entire entry - Track the number of "tail" entries in a pte_list_desc to avoid having to walk (potentially) all descriptors during insertion and deletion, which gets quite expensive if the guest is spamming fork() - Misc cleanups
2 parents a1c288f + 9ed3bf4 commit 807b758

14 files changed

Lines changed: 515 additions & 567 deletions

File tree

arch/x86/include/asm/kvm-x86-ops.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ KVM_X86_OP(set_rflags)
5454
KVM_X86_OP(get_if_flag)
5555
KVM_X86_OP(flush_tlb_all)
5656
KVM_X86_OP(flush_tlb_current)
57-
KVM_X86_OP_OPTIONAL(tlb_remote_flush)
58-
KVM_X86_OP_OPTIONAL(tlb_remote_flush_with_range)
57+
KVM_X86_OP_OPTIONAL(flush_remote_tlbs)
58+
KVM_X86_OP_OPTIONAL(flush_remote_tlbs_range)
5959
KVM_X86_OP(flush_tlb_gva)
6060
KVM_X86_OP(flush_tlb_guest)
6161
KVM_X86_OP(vcpu_pre_run)

arch/x86/include/asm/kvm_host.h

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,10 @@ struct kvm_mmu_root_info {
420420

421421
#define KVM_MMU_NUM_PREV_ROOTS 3
422422

423+
#define KVM_MMU_ROOT_CURRENT BIT(0)
424+
#define KVM_MMU_ROOT_PREVIOUS(i) BIT(1+i)
425+
#define KVM_MMU_ROOTS_ALL (BIT(1 + KVM_MMU_NUM_PREV_ROOTS) - 1)
426+
423427
#define KVM_HAVE_MMU_RWLOCK
424428

425429
struct kvm_mmu_page;
@@ -439,9 +443,8 @@ struct kvm_mmu {
439443
gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
440444
gpa_t gva_or_gpa, u64 access,
441445
struct x86_exception *exception);
442-
int (*sync_page)(struct kvm_vcpu *vcpu,
443-
struct kvm_mmu_page *sp);
444-
void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva, hpa_t root_hpa);
446+
int (*sync_spte)(struct kvm_vcpu *vcpu,
447+
struct kvm_mmu_page *sp, int i);
445448
struct kvm_mmu_root_info root;
446449
union kvm_cpu_role cpu_role;
447450
union kvm_mmu_page_role root_role;
@@ -479,11 +482,6 @@ struct kvm_mmu {
479482
u64 pdptrs[4]; /* pae */
480483
};
481484

482-
struct kvm_tlb_range {
483-
u64 start_gfn;
484-
u64 pages;
485-
};
486-
487485
enum pmc_type {
488486
KVM_PMC_GP = 0,
489487
KVM_PMC_FIXED,
@@ -1585,9 +1583,9 @@ struct kvm_x86_ops {
15851583

15861584
void (*flush_tlb_all)(struct kvm_vcpu *vcpu);
15871585
void (*flush_tlb_current)(struct kvm_vcpu *vcpu);
1588-
int (*tlb_remote_flush)(struct kvm *kvm);
1589-
int (*tlb_remote_flush_with_range)(struct kvm *kvm,
1590-
struct kvm_tlb_range *range);
1586+
int (*flush_remote_tlbs)(struct kvm *kvm);
1587+
int (*flush_remote_tlbs_range)(struct kvm *kvm, gfn_t gfn,
1588+
gfn_t nr_pages);
15911589

15921590
/*
15931591
* Flush any TLB entries associated with the given GVA.
@@ -1791,8 +1789,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
17911789
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLB
17921790
static inline int kvm_arch_flush_remote_tlb(struct kvm *kvm)
17931791
{
1794-
if (kvm_x86_ops.tlb_remote_flush &&
1795-
!static_call(kvm_x86_tlb_remote_flush)(kvm))
1792+
if (kvm_x86_ops.flush_remote_tlbs &&
1793+
!static_call(kvm_x86_flush_remote_tlbs)(kvm))
17961794
return 0;
17971795
else
17981796
return -ENOTSUPP;
@@ -1997,10 +1995,6 @@ static inline int __kvm_irq_line_state(unsigned long *irq_state,
19971995
return !!(*irq_state);
19981996
}
19991997

2000-
#define KVM_MMU_ROOT_CURRENT BIT(0)
2001-
#define KVM_MMU_ROOT_PREVIOUS(i) BIT(1+i)
2002-
#define KVM_MMU_ROOTS_ALL (~0UL)
2003-
20041998
int kvm_pic_set_irq(struct kvm_pic *pic, int irq, int irq_source_id, int level);
20051999
void kvm_pic_clear_all(struct kvm_pic *pic, int irq_source_id);
20062000

@@ -2044,8 +2038,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
20442038
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
20452039
void *insn, int insn_len);
20462040
void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
2047-
void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
2048-
gva_t gva, hpa_t root_hpa);
2041+
void kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
2042+
u64 addr, unsigned long roots);
20492043
void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid);
20502044
void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd);
20512045

arch/x86/kvm/kvm_onhyperv.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@
1010
#include "hyperv.h"
1111
#include "kvm_onhyperv.h"
1212

13+
struct kvm_hv_tlb_range {
14+
u64 start_gfn;
15+
u64 pages;
16+
};
17+
1318
static int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
1419
void *data)
1520
{
16-
struct kvm_tlb_range *range = data;
21+
struct kvm_hv_tlb_range *range = data;
1722

1823
return hyperv_fill_flush_guest_mapping_list(flush, range->start_gfn,
1924
range->pages);
2025
}
2126

2227
static inline int hv_remote_flush_root_tdp(hpa_t root_tdp,
23-
struct kvm_tlb_range *range)
28+
struct kvm_hv_tlb_range *range)
2429
{
2530
if (range)
2631
return hyperv_flush_guest_mapping_range(root_tdp,
@@ -29,8 +34,8 @@ static inline int hv_remote_flush_root_tdp(hpa_t root_tdp,
2934
return hyperv_flush_guest_mapping(root_tdp);
3035
}
3136

32-
int hv_remote_flush_tlb_with_range(struct kvm *kvm,
33-
struct kvm_tlb_range *range)
37+
static int __hv_flush_remote_tlbs_range(struct kvm *kvm,
38+
struct kvm_hv_tlb_range *range)
3439
{
3540
struct kvm_arch *kvm_arch = &kvm->arch;
3641
struct kvm_vcpu *vcpu;
@@ -86,19 +91,29 @@ int hv_remote_flush_tlb_with_range(struct kvm *kvm,
8691
spin_unlock(&kvm_arch->hv_root_tdp_lock);
8792
return ret;
8893
}
89-
EXPORT_SYMBOL_GPL(hv_remote_flush_tlb_with_range);
9094

91-
int hv_remote_flush_tlb(struct kvm *kvm)
95+
int hv_flush_remote_tlbs_range(struct kvm *kvm, gfn_t start_gfn, gfn_t nr_pages)
96+
{
97+
struct kvm_hv_tlb_range range = {
98+
.start_gfn = start_gfn,
99+
.pages = nr_pages,
100+
};
101+
102+
return __hv_flush_remote_tlbs_range(kvm, &range);
103+
}
104+
EXPORT_SYMBOL_GPL(hv_flush_remote_tlbs_range);
105+
106+
int hv_flush_remote_tlbs(struct kvm *kvm)
92107
{
93-
return hv_remote_flush_tlb_with_range(kvm, NULL);
108+
return __hv_flush_remote_tlbs_range(kvm, NULL);
94109
}
95-
EXPORT_SYMBOL_GPL(hv_remote_flush_tlb);
110+
EXPORT_SYMBOL_GPL(hv_flush_remote_tlbs);
96111

97112
void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp)
98113
{
99114
struct kvm_arch *kvm_arch = &vcpu->kvm->arch;
100115

101-
if (kvm_x86_ops.tlb_remote_flush == hv_remote_flush_tlb) {
116+
if (kvm_x86_ops.flush_remote_tlbs == hv_flush_remote_tlbs) {
102117
spin_lock(&kvm_arch->hv_root_tdp_lock);
103118
vcpu->arch.hv_root_tdp = root_tdp;
104119
if (root_tdp != kvm_arch->hv_root_tdp)

arch/x86/kvm/kvm_onhyperv.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
#define __ARCH_X86_KVM_KVM_ONHYPERV_H__
88

99
#if IS_ENABLED(CONFIG_HYPERV)
10-
int hv_remote_flush_tlb_with_range(struct kvm *kvm,
11-
struct kvm_tlb_range *range);
12-
int hv_remote_flush_tlb(struct kvm *kvm);
10+
int hv_flush_remote_tlbs_range(struct kvm *kvm, gfn_t gfn, gfn_t nr_pages);
11+
int hv_flush_remote_tlbs(struct kvm *kvm);
1312
void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
1413
#else /* !CONFIG_HYPERV */
1514
static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp)

0 commit comments

Comments
 (0)