Skip to content

Commit 617ab45

Browse files
vittyvkKAGA-KOKO
authored andcommitted
x86/hyperv: Stop suppressing X86_FEATURE_PCID
When hypercall-based TLB flush was enabled for Hyper-V guests PCID feature was deliberately suppressed as a precaution: back then PCID was never exposed to Hyper-V guests and it wasn't clear what will happen if some day it becomes available. The day came and PCID/INVPCID features are already exposed on certain Hyper-V hosts. From TLFS (as of 5.0b) it is unclear how TLB flush hypercalls combine with PCID. In particular the usage of PCID is per-cpu based: the same mm gets different CR3 values on different CPUs. If the hypercall does exact matching this will fail. However, this is not the case. David Zhang explains: "In practice, the AddressSpace argument is ignored on any VM that supports PCIDs. Architecturally, the AddressSpace argument must match the CR3 with PCID bits stripped out (i.e., the low 12 bits of AddressSpace should be 0 in long mode). The flush hypercalls flush all PCIDs for the specified AddressSpace." With this, PCID can be enabled. Signed-off-by: Vitaly Kuznetsov <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: David Zhang <[email protected]> Cc: Stephen Hemminger <[email protected]> Cc: Haiyang Zhang <[email protected]> Cc: "Michael Kelley (EOSG)" <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: [email protected] Cc: "K. Y. Srinivasan" <[email protected]> Cc: Aditya Bhandari <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 1f07476 commit 617ab45

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

arch/x86/hyperv/mmu.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,12 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
137137
}
138138

139139
if (info->mm) {
140+
/*
141+
* AddressSpace argument must match the CR3 with PCID bits
142+
* stripped out.
143+
*/
140144
flush->address_space = virt_to_phys(info->mm->pgd);
145+
flush->address_space &= CR3_ADDR_MASK;
141146
flush->flags = 0;
142147
} else {
143148
flush->address_space = 0;
@@ -219,7 +224,12 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
219224
}
220225

221226
if (info->mm) {
227+
/*
228+
* AddressSpace argument must match the CR3 with PCID bits
229+
* stripped out.
230+
*/
222231
flush->address_space = virt_to_phys(info->mm->pgd);
232+
flush->address_space &= CR3_ADDR_MASK;
223233
flush->flags = 0;
224234
} else {
225235
flush->address_space = 0;
@@ -278,8 +288,6 @@ void hyperv_setup_mmu_ops(void)
278288
if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED))
279289
return;
280290

281-
setup_clear_cpu_cap(X86_FEATURE_PCID);
282-
283291
if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) {
284292
pr_info("Using hypercall for remote TLB flush\n");
285293
pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;

0 commit comments

Comments
 (0)