2024-04-18 20:54:39

by Xi Ruoyao

[permalink] [raw]
Subject: [PATCH v9 1/2] x86/mm: Don't disable PCID if "incomplete Global INVLPG flushes" is fixed by microcode

Per the "Processor Specification Update" documentations referred by the
intel-microcode-20240312 release note, this microcode release has fixed
the issue for all affected models.

So don't disable PCID if the microcode is new enough. The precise
minimum microcode revision fixing the issue is provided by engineer from
Intel.

Cc: Dave Hansen <[email protected]>
Cc: Michael Kelley <[email protected]>
Cc: Pawan Gupta <[email protected]>
Cc: Sean Christopherson <[email protected]>
Cc: Andrew Cooper <[email protected]>
Link: https://lore.kernel.org/all/168436059559.404.13934972543631851306.tip-bot2@tip-bot2/
Link: https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/releases/tag/microcode-20240312
Link: https://cdrdv2.intel.com/v1/dl/getContent/740518 # RPL042, rev. 13
Link: https://cdrdv2.intel.com/v1/dl/getContent/682436 # ADL063, rev. 24
Link: https://lore.kernel.org/all/20240325231300.qrltbzf6twm43ftb@desk/
Signed-off-by: Xi Ruoyao <[email protected]>
---
arch/x86/mm/init.c | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 679893ea5e68..c318cdc35467 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -261,33 +261,43 @@ static void __init probe_page_size_mask(void)
}
}

-#define INTEL_MATCH(_model) { .vendor = X86_VENDOR_INTEL, \
- .family = 6, \
- .model = _model, \
- }
+#define INTEL_MATCH(_model, _fixed_microcode) \
+ { \
+ .vendor = X86_VENDOR_INTEL, \
+ .family = 6, \
+ .model = _model, \
+ .driver_data = _fixed_microcode, \
+ }
+
/*
* INVLPG may not properly flush Global entries
- * on these CPUs when PCIDs are enabled.
+ * on these CPUs when PCIDs are enabled and the
+ * microcode is not updated to fix the issue.
*/
static const struct x86_cpu_id invlpg_miss_ids[] = {
- INTEL_MATCH(INTEL_FAM6_ALDERLAKE ),
- INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ),
- INTEL_MATCH(INTEL_FAM6_ATOM_GRACEMONT ),
- INTEL_MATCH(INTEL_FAM6_RAPTORLAKE ),
- INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P),
- INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S),
+ INTEL_MATCH(INTEL_FAM6_ALDERLAKE, 0x2e),
+ INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L, 0x42c),
+ INTEL_MATCH(INTEL_FAM6_ATOM_GRACEMONT, 0x11),
+ INTEL_MATCH(INTEL_FAM6_RAPTORLAKE, 0x118),
+ INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P, 0x4117),
+ INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S, 0x2e),
{}
};

static void setup_pcid(void)
{
+ const struct x86_cpu_id *invlpg_miss_match;
+
if (!IS_ENABLED(CONFIG_X86_64))
return;

if (!boot_cpu_has(X86_FEATURE_PCID))
return;

- if (x86_match_cpu(invlpg_miss_ids)) {
+ invlpg_miss_match = x86_match_cpu(invlpg_miss_ids);
+
+ if (invlpg_miss_match &&
+ boot_cpu_data.microcode < invlpg_miss_match->driver_data) {
pr_info("Incomplete global flushes, disabling PCID");
setup_clear_cpu_cap(X86_FEATURE_PCID);
return;
--
2.44.0



2024-04-18 20:54:51

by Xi Ruoyao

[permalink] [raw]
Subject: [PATCH v9 2/2] x86/mm: Don't disable PCID if the kernel is running on a hypervisor

The Intel erratum for "incomplete Global INVLPG flushes" says:

This erratum does not apply in VMX non-root operation. It applies
only when PCIDs are enabled and either in VMX root operation or
outside VMX operation.

So if the kernel is running in a hypervisor, we are in VMX non-root
operation and we should be safe to use PCID.

Cc: Dave Hansen <[email protected]>
Cc: Michael Kelley <[email protected]>
Cc: Pawan Gupta <[email protected]>
Cc: Sean Christopherson <[email protected]>
Cc: Andrew Cooper <[email protected]>
Link: https://lore.kernel.org/all/168436059559.404.13934972543631851306.tip-bot2@tip-bot2/
Link: https://cdrdv2.intel.com/v1/dl/getContent/740518 # RPL042, rev. 13
Link: https://cdrdv2.intel.com/v1/dl/getContent/682436 # ADL063, rev. 24
Signed-off-by: Xi Ruoyao <[email protected]>
---
arch/x86/mm/init.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index c318cdc35467..b20e453c1217 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -286,7 +286,7 @@ static const struct x86_cpu_id invlpg_miss_ids[] = {

static void setup_pcid(void)
{
- const struct x86_cpu_id *invlpg_miss_match;
+ const struct x86_cpu_id *invlpg_miss_match = NULL;

if (!IS_ENABLED(CONFIG_X86_64))
return;
@@ -294,7 +294,9 @@ static void setup_pcid(void)
if (!boot_cpu_has(X86_FEATURE_PCID))
return;

- invlpg_miss_match = x86_match_cpu(invlpg_miss_ids);
+ /* Only bare-metal is affected. PCIDs in guests are OK. */
+ if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
+ invlpg_miss_match = x86_match_cpu(invlpg_miss_ids);

if (invlpg_miss_match &&
boot_cpu_data.microcode < invlpg_miss_match->driver_data) {
--
2.44.0