Skip to content

Commit 635de95

Browse files
committed
Merge tag 'x86-mm-2021-04-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 tlb updates from Ingo Molnar: "The x86 MM changes in this cycle were: - Implement concurrent TLB flushes, which overlaps the local TLB flush with the remote TLB flush. In testing this improved sysbench performance measurably by a couple of percentage points, especially if TLB-heavy security mitigations are active. - Further micro-optimizations to improve the performance of TLB flushes" * tag 'x86-mm-2021-04-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: smp: Micro-optimize smp_call_function_many_cond() smp: Inline on_each_cpu_cond() and on_each_cpu() x86/mm/tlb: Remove unnecessary uses of the inline keyword cpumask: Mark functions as pure x86/mm/tlb: Do not make is_lazy dirty for no reason x86/mm/tlb: Privatize cpu_tlbstate x86/mm/tlb: Flush remote and local TLBs concurrently x86/mm/tlb: Open-code on_each_cpu_cond_mask() for tlb_is_not_lazy() x86/mm/tlb: Unify flush_tlb_func_local() and flush_tlb_func_remote() smp: Run functions concurrently in smp_call_function_many_cond()
2 parents d0cc7ec + a500fc9 commit 635de95

File tree

16 files changed

+287
-295
lines changed

16 files changed

+287
-295
lines changed

arch/x86/hyperv/mmu.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ static inline int fill_gva_list(u64 gva_list[], int offset,
5252
return gva_n - offset;
5353
}
5454

55-
static void hyperv_flush_tlb_others(const struct cpumask *cpus,
56-
const struct flush_tlb_info *info)
55+
static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
56+
const struct flush_tlb_info *info)
5757
{
5858
int cpu, vcpu, gva_n, max_gvas;
5959
struct hv_tlb_flush **flush_pcpu;
6060
struct hv_tlb_flush *flush;
6161
u64 status;
6262
unsigned long flags;
6363

64-
trace_hyperv_mmu_flush_tlb_others(cpus, info);
64+
trace_hyperv_mmu_flush_tlb_multi(cpus, info);
6565

6666
if (!hv_hypercall_pg)
6767
goto do_native;
@@ -164,7 +164,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
164164
if (hv_result_success(status))
165165
return;
166166
do_native:
167-
native_flush_tlb_others(cpus, info);
167+
native_flush_tlb_multi(cpus, info);
168168
}
169169

170170
static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
@@ -239,6 +239,6 @@ void hyperv_setup_mmu_ops(void)
239239
return;
240240

241241
pr_info("Using hypercall for remote TLB flush\n");
242-
pv_ops.mmu.flush_tlb_others = hyperv_flush_tlb_others;
242+
pv_ops.mmu.flush_tlb_multi = hyperv_flush_tlb_multi;
243243
pv_ops.mmu.tlb_remove_table = tlb_remove_table;
244244
}

arch/x86/include/asm/paravirt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static inline void slow_down_io(void)
6363
void native_flush_tlb_local(void);
6464
void native_flush_tlb_global(void);
6565
void native_flush_tlb_one_user(unsigned long addr);
66-
void native_flush_tlb_others(const struct cpumask *cpumask,
66+
void native_flush_tlb_multi(const struct cpumask *cpumask,
6767
const struct flush_tlb_info *info);
6868

6969
static inline void __flush_tlb_local(void)
@@ -81,10 +81,10 @@ static inline void __flush_tlb_one_user(unsigned long addr)
8181
PVOP_VCALL1(mmu.flush_tlb_one_user, addr);
8282
}
8383

84-
static inline void __flush_tlb_others(const struct cpumask *cpumask,
84+
static inline void __flush_tlb_multi(const struct cpumask *cpumask,
8585
const struct flush_tlb_info *info)
8686
{
87-
PVOP_VCALL2(mmu.flush_tlb_others, cpumask, info);
87+
PVOP_VCALL2(mmu.flush_tlb_multi, cpumask, info);
8888
}
8989

9090
static inline void paravirt_tlb_remove_table(struct mmu_gather *tlb, void *table)

arch/x86/include/asm/paravirt_types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ struct pv_mmu_ops {
161161
void (*flush_tlb_user)(void);
162162
void (*flush_tlb_kernel)(void);
163163
void (*flush_tlb_one_user)(unsigned long addr);
164-
void (*flush_tlb_others)(const struct cpumask *cpus,
165-
const struct flush_tlb_info *info);
164+
void (*flush_tlb_multi)(const struct cpumask *cpus,
165+
const struct flush_tlb_info *info);
166166

167167
void (*tlb_remove_table)(struct mmu_gather *tlb, void *table);
168168

arch/x86/include/asm/tlbflush.h

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,6 @@ struct tlb_state {
8989
u16 loaded_mm_asid;
9090
u16 next_asid;
9191

92-
/*
93-
* We can be in one of several states:
94-
*
95-
* - Actively using an mm. Our CPU's bit will be set in
96-
* mm_cpumask(loaded_mm) and is_lazy == false;
97-
*
98-
* - Not using a real mm. loaded_mm == &init_mm. Our CPU's bit
99-
* will not be set in mm_cpumask(&init_mm) and is_lazy == false.
100-
*
101-
* - Lazily using a real mm. loaded_mm != &init_mm, our bit
102-
* is set in mm_cpumask(loaded_mm), but is_lazy == true.
103-
* We're heuristically guessing that the CR3 load we
104-
* skipped more than makes up for the overhead added by
105-
* lazy mode.
106-
*/
107-
bool is_lazy;
108-
10992
/*
11093
* If set we changed the page tables in such a way that we
11194
* needed an invalidation of all contexts (aka. PCIDs / ASIDs).
@@ -151,7 +134,27 @@ struct tlb_state {
151134
*/
152135
struct tlb_context ctxs[TLB_NR_DYN_ASIDS];
153136
};
154-
DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
137+
DECLARE_PER_CPU_ALIGNED(struct tlb_state, cpu_tlbstate);
138+
139+
struct tlb_state_shared {
140+
/*
141+
* We can be in one of several states:
142+
*
143+
* - Actively using an mm. Our CPU's bit will be set in
144+
* mm_cpumask(loaded_mm) and is_lazy == false;
145+
*
146+
* - Not using a real mm. loaded_mm == &init_mm. Our CPU's bit
147+
* will not be set in mm_cpumask(&init_mm) and is_lazy == false.
148+
*
149+
* - Lazily using a real mm. loaded_mm != &init_mm, our bit
150+
* is set in mm_cpumask(loaded_mm), but is_lazy == true.
151+
* We're heuristically guessing that the CR3 load we
152+
* skipped more than makes up for the overhead added by
153+
* lazy mode.
154+
*/
155+
bool is_lazy;
156+
};
157+
DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
155158

156159
bool nmi_uaccess_okay(void);
157160
#define nmi_uaccess_okay nmi_uaccess_okay
@@ -175,7 +178,7 @@ extern void initialize_tlbstate_and_flush(void);
175178
* - flush_tlb_page(vma, vmaddr) flushes one page
176179
* - flush_tlb_range(vma, start, end) flushes a range of pages
177180
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
178-
* - flush_tlb_others(cpumask, info) flushes TLBs on other cpus
181+
* - flush_tlb_multi(cpumask, info) flushes TLBs on multiple cpus
179182
*
180183
* ..but the i386 has somewhat limited tlb flushing capabilities,
181184
* and page-granular flushes are available only on i486 and up.
@@ -201,14 +204,15 @@ struct flush_tlb_info {
201204
unsigned long start;
202205
unsigned long end;
203206
u64 new_tlb_gen;
204-
unsigned int stride_shift;
205-
bool freed_tables;
207+
unsigned int initiating_cpu;
208+
u8 stride_shift;
209+
u8 freed_tables;
206210
};
207211

208212
void flush_tlb_local(void);
209213
void flush_tlb_one_user(unsigned long addr);
210214
void flush_tlb_one_kernel(unsigned long addr);
211-
void flush_tlb_others(const struct cpumask *cpumask,
215+
void flush_tlb_multi(const struct cpumask *cpumask,
212216
const struct flush_tlb_info *info);
213217

214218
#ifdef CONFIG_PARAVIRT

arch/x86/include/asm/trace/hyperv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#if IS_ENABLED(CONFIG_HYPERV)
1010

11-
TRACE_EVENT(hyperv_mmu_flush_tlb_others,
11+
TRACE_EVENT(hyperv_mmu_flush_tlb_multi,
1212
TP_PROTO(const struct cpumask *cpus,
1313
const struct flush_tlb_info *info),
1414
TP_ARGS(cpus, info),

arch/x86/kernel/alternative.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ static inline temp_mm_state_t use_temporary_mm(struct mm_struct *mm)
706706
* with a stale address space WITHOUT being in lazy mode after
707707
* restoring the previous mm.
708708
*/
709-
if (this_cpu_read(cpu_tlbstate.is_lazy))
709+
if (this_cpu_read(cpu_tlbstate_shared.is_lazy))
710710
leave_mm(smp_processor_id());
711711

712712
temp_state.mm = this_cpu_read(cpu_tlbstate.loaded_mm);

arch/x86/kernel/kvm.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ static int kvm_cpu_down_prepare(unsigned int cpu)
613613
}
614614
#endif
615615

616-
static void kvm_flush_tlb_others(const struct cpumask *cpumask,
616+
static void kvm_flush_tlb_multi(const struct cpumask *cpumask,
617617
const struct flush_tlb_info *info)
618618
{
619619
u8 state;
@@ -627,6 +627,11 @@ static void kvm_flush_tlb_others(const struct cpumask *cpumask,
627627
* queue flush_on_enter for pre-empted vCPUs
628628
*/
629629
for_each_cpu(cpu, flushmask) {
630+
/*
631+
* The local vCPU is never preempted, so we do not explicitly
632+
* skip check for local vCPU - it will never be cleared from
633+
* flushmask.
634+
*/
630635
src = &per_cpu(steal_time, cpu);
631636
state = READ_ONCE(src->preempted);
632637
if ((state & KVM_VCPU_PREEMPTED)) {
@@ -636,7 +641,7 @@ static void kvm_flush_tlb_others(const struct cpumask *cpumask,
636641
}
637642
}
638643

639-
native_flush_tlb_others(flushmask, info);
644+
native_flush_tlb_multi(flushmask, info);
640645
}
641646

642647
static void __init kvm_guest_init(void)
@@ -654,7 +659,7 @@ static void __init kvm_guest_init(void)
654659
}
655660

656661
if (pv_tlb_flush_supported()) {
657-
pv_ops.mmu.flush_tlb_others = kvm_flush_tlb_others;
662+
pv_ops.mmu.flush_tlb_multi = kvm_flush_tlb_multi;
658663
pv_ops.mmu.tlb_remove_table = tlb_remove_table;
659664
pr_info("KVM setup pv remote TLB flush\n");
660665
}

arch/x86/kernel/paravirt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ struct paravirt_patch_template pv_ops = {
291291
.mmu.flush_tlb_user = native_flush_tlb_local,
292292
.mmu.flush_tlb_kernel = native_flush_tlb_global,
293293
.mmu.flush_tlb_one_user = native_flush_tlb_one_user,
294-
.mmu.flush_tlb_others = native_flush_tlb_others,
294+
.mmu.flush_tlb_multi = native_flush_tlb_multi,
295295
.mmu.tlb_remove_table =
296296
(void (*)(struct mmu_gather *, void *))tlb_remove_page,
297297

arch/x86/mm/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ void __init zone_sizes_init(void)
10171017
free_area_init(max_zone_pfns);
10181018
}
10191019

1020-
__visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
1020+
__visible DEFINE_PER_CPU_ALIGNED(struct tlb_state, cpu_tlbstate) = {
10211021
.loaded_mm = &init_mm,
10221022
.next_asid = 1,
10231023
.cr4 = ~0UL, /* fail hard if we screw up cr4 shadow initialization */

0 commit comments

Comments
 (0)