Skip to content

Commit 493cc07

Browse files
kelleymhliuw
authored andcommitted
x86/hyperv: Exclude lazy TLB mode CPUs from enlightened TLB flushes
In the case where page tables are not freed, native_flush_tlb_multi() does not do a remote TLB flush on CPUs in lazy TLB mode because the CPU will flush itself at the next context switch. By comparison, the Hyper-V enlightened TLB flush does not exclude CPUs in lazy TLB mode and so performs unnecessary flushes. If we're not freeing page tables, add logic to test for lazy TLB mode when adding CPUs to the input argument to the Hyper-V TLB flush hypercall. Exclude lazy TLB mode CPUs so the behavior matches native_flush_tlb_multi() and the unnecessary flushes are avoided. Handle both the <=64 vCPU case and the _ex case for >64 vCPUs. Signed-off-by: Michael Kelley <mikelley@microsoft.com> Link: https://lore.kernel.org/r/1679922967-26582-3-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
1 parent d7b6ba9 commit 493cc07

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

arch/x86/hyperv/mmu.c

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

55+
static bool cpu_is_lazy(int cpu)
56+
{
57+
return per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
58+
}
59+
5560
static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
5661
const struct flush_tlb_info *info)
5762
{
@@ -60,6 +65,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
6065
struct hv_tlb_flush *flush;
6166
u64 status;
6267
unsigned long flags;
68+
bool do_lazy = !info->freed_tables;
6369

6470
trace_hyperv_mmu_flush_tlb_multi(cpus, info);
6571

@@ -112,6 +118,8 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
112118
goto do_ex_hypercall;
113119

114120
for_each_cpu(cpu, cpus) {
121+
if (do_lazy && cpu_is_lazy(cpu))
122+
continue;
115123
vcpu = hv_cpu_number_to_vp_number(cpu);
116124
if (vcpu == VP_INVAL) {
117125
local_irq_restore(flags);
@@ -198,7 +206,8 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
198206
flush->hv_vp_set.valid_bank_mask = 0;
199207

200208
flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K;
201-
nr_bank = cpumask_to_vpset(&(flush->hv_vp_set), cpus);
209+
nr_bank = cpumask_to_vpset_skip(&flush->hv_vp_set, cpus,
210+
info->freed_tables ? NULL : cpu_is_lazy);
202211
if (nr_bank < 0)
203212
return HV_STATUS_INVALID_PARAMETER;
204213

0 commit comments

Comments
 (0)