x86/hyper-v: stop suppressing X86_FEATURE_PCID
Subsystems (2)
PATCH 1/1 x86/hyper-v: 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.
I was asked if we can stop suppressing PCID. From TLFS (as of 5.0b) is is unclear how TLB flush hypercalls combine with PCID. In particular, I was worried about our usage of PCID where it is per-cpu based: the same mm gets different CR3 values on different CPUs and if hypercall does exact matching we're screwed. However, this is not the case. David Zhang writes:
"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.
--- arch/x86/hyperv/mmu.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
arch/x86/hyperv/mmu.c +12 -4
@@ -137,7 +137,12 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, }if (info->mm) { - flush->address_space =virt_to_phys (info->mm->pgd); +/* +* AddressSpace argument must match the CR3 with PCID bits +* stripped out. +*/ + flush->address_space = +virt_to_phys (info->mm->pgd) &CR3_ADDR_MASK ; flush->flags =0 ; }else { flush->address_space =0 ;
@@ -219,7 +224,12 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, }if (info->mm) { - flush->address_space =virt_to_phys (info->mm->pgd); +/* +* AddressSpace argument must match the CR3 with PCID bits +* stripped out. +*/ + flush->address_space = +virt_to_phys (info->mm->pgd) &CR3_ADDR_MASK ; flush->flags =0 ; }else { flush->address_space =0 ;
@@ -278,8 +288,6 @@ void hyperv_setup_mmu_ops(void)if (!(ms_hyperv.hints &HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED ))return ; -setup_clear_cpu_cap (X86_FEATURE_PCID ); -if (!(ms_hyperv.hints &HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED )) {pr_info ("Using hypercall for remote TLB flush\n" ); pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;
Signature · 6 lines
2.14.3 _______________________________________________ devel mailing list [email protected] http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
tip-bot for Vitaly Kuznetsov
merge bot[tip:x86/hyperv] x86/hyperv: Stop suppressing X86_FEATURE_PCID
x86/hyperv: Stop suppressing X86_FEATURE_PCID
Commit-ID: 04651dd978a8749e59065df14b970a127f219ac2 Gitweb: https://git.kernel.org/tip/04651dd978a8749e59065df14b970a127f219ac2 Author: Vitaly Kuznetsov <[email protected]> AuthorDate: Wed, 24 Jan 2018 11:36:29 +0100 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 24 Jan 2018 13:44:57 +0100
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.
Quoted 1 line
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.
--- arch/x86/hyperv/mmu.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
arch/x86/hyperv/mmu.c +11 -3
@@ -111,7 +111,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,int cpu, vcpu, gva_n, max_gvas;struct hv_flush_pcpu **flush_pcpu;struct hv_flush_pcpu *flush; -u64 status =U64_MAX ; +u64 base, status =U64_MAX ;unsigned long flags;trace_hyperv_mmu_flush_tlb_others (cpus, info);
@@ -137,7 +137,12 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, }if (info->mm) { +/* +* AddressSpace argument must match the CR3 with PCID bits +* stripped out. +*/ flush->address_space =virt_to_phys (info->mm->pgd); + flush->address_space &=CR3_ADDR_MASK ; flush->flags =0 ; }else { flush->address_space =0 ;
@@ -219,7 +224,12 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, }if (info->mm) { +/* +* AddressSpace argument must match the CR3 with PCID bits +* stripped out. +*/ flush->address_space =virt_to_phys (info->mm->pgd); + flush->address_space &=CR3_ADDR_MASK ; flush->flags =0 ; }else { flush->address_space =0 ;
@@ -278,8 +288,6 @@ void hyperv_setup_mmu_ops(void)if (!(ms_hyperv.hints &HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED ))return ; -setup_clear_cpu_cap (X86_FEATURE_PCID ); -if (!(ms_hyperv.hints &HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED )) {pr_info ("Using hypercall for remote TLB flush\n" ); pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;
Re: [tip:x86/hyperv] x86/hyperv: Stop suppressing X86_FEATURE_PCID
Quoted 24 lines · tip-bot for Vitaly Kuznetsov
Commit-ID: 04651dd978a8749e59065df14b970a127f219ac2 Gitweb: https://git.kernel.org/tip/04651dd978a8749e59065df14b970a127f219ac2 Author: Vitaly Kuznetsov <[email protected]> AuthorDate: Wed, 24 Jan 2018 11:36:29 +0100 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 24 Jan 2018 13:44:57 +0100x86/hyperv: Stop suppressing
X86_FEATURE_PCIDWhen 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.
Quoted 6 lines
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.
So what, exactly, does the flush hypercall do?
--Andy
RE: [tip:x86/hyperv] x86/hyperv: Stop suppressing X86_FEATURE_PCID
When the FLUSH_ALL_VIRTUAL_ADDRESS_SPACES flag (0x2) is not specified, the flush hypercall matches the AddressSpace parameter with the base address of the page table root on each processor (the base address is page-aligned in long/32-bit mode, 32-byte aligned in PAE mode). If there is a match, it flushes the specified VAs, for all PCIDs.
The flush hypercall is allowed to flush more than the above, however.
We will update the TLFS with this behavior.
-----Original Message-----
From: Andy Lutomirski [mailto:[email protected]]
Sent: Wednesday, January 24, 2018 8:28 AM
To: David Zhang <[email protected]>; Haiyang Zhang <[email protected]>; KY Srinivasan <[email protected]>; LKML <[email protected]>; H. Peter Anvin <[email protected]>; Andrew Lutomirski <[email protected]>; Vitaly Kuznetsov <[email protected]>; Thomas Gleixner <[email protected]>; Michael Kelley (EOSG) <[email protected]>; Aditya Bhandari <[email protected]>; Ingo Molnar <[email protected]>; Stephen Hemminger <[email protected]>
Cc: [email protected]
Subject: Re: [tip:x86/hyperv] x86/hyperv: Stop suppressing X86_FEATURE_PCID
Quoted 25 lines · tip-bot for Vitaly Kuznetsov
Commit-ID: 04651dd978a8749e59065df14b970a127f219ac2 Gitweb: https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Ftip%2F04651dd978a8749e59065df14b970a127f219ac2&data=02%7C01%7Cdazhan%40microsoft.com%7C59a83800e5b84e1bb97008d56347705b%7Cee3303d7fb734b0c8589bcd847f1c277%7C1%7C0%7C636524080843155861&sdata=qA5eG6L9MieOSWL8SCBQaWcYJtN7IT75rO0I1PdoZ%2FE%3D&reserved=0 Author: Vitaly Kuznetsov <[email protected]> AuthorDate: Wed, 24 Jan 2018 11:36:29 +0100 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 24 Jan 2018 13:44:57 +0100x86/hyperv: Stop suppressing
X86_FEATURE_PCIDWhen 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.
Quoted 6 lines
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.
So what, exactly, does the flush hypercall do?
--Andy
tip-bot for Vitaly Kuznetsov
merge bot[tip:x86/hyperv] x86/hyperv: Stop suppressing X86_FEATURE_PCID
In reply to Vitaly Kuznetsovx86/hyperv: Stop suppressing X86_FEATURE_PCID
Commit-ID: 617ab45c9a8900e64a78b43696c02598b8cad68b Gitweb: https://git.kernel.org/tip/617ab45c9a8900e64a78b43696c02598b8cad68b Author: Vitaly Kuznetsov <[email protected]> AuthorDate: Wed, 24 Jan 2018 11:36:29 +0100 Committer: Thomas Gleixner <[email protected]> CommitDate: Thu, 25 Jan 2018 09:40:59 +0100
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.
Quoted 1 line
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.
--- arch/x86/hyperv/mmu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
arch/x86/hyperv/mmu.c +10 -2
@@ -137,7 +137,12 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, }if (info->mm) { +/* +* AddressSpace argument must match the CR3 with PCID bits +* stripped out. +*/ flush->address_space =virt_to_phys (info->mm->pgd); + flush->address_space &=CR3_ADDR_MASK ; flush->flags =0 ; }else { flush->address_space =0 ;
@@ -219,7 +224,12 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, }if (info->mm) { +/* +* AddressSpace argument must match the CR3 with PCID bits +* stripped out. +*/ flush->address_space =virt_to_phys (info->mm->pgd); + flush->address_space &=CR3_ADDR_MASK ; flush->flags =0 ; }else { flush->address_space =0 ;
@@ -278,8 +288,6 @@ void hyperv_setup_mmu_ops(void)if (!(ms_hyperv.hints &HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED ))return ; -setup_clear_cpu_cap (X86_FEATURE_PCID ); -if (!(ms_hyperv.hints &HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED )) {pr_info ("Using hypercall for remote TLB flush\n" ); pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;