Re: [RFC 05/10] x86/speculation: Add basic IBRS support infrastructure

From: Peter Zijlstra
Date: Wed Jan 24 2018 - 03:47:59 EST


On Tue, Jan 23, 2018 at 08:58:36PM +0000, David Woodhouse wrote:

> +static const struct sku_microcode spectre_bad_microcodes[] = {
> + { INTEL_FAM6_KABYLAKE_DESKTOP, 0x0B, 0x80 },
> + { INTEL_FAM6_KABYLAKE_MOBILE, 0x0A, 0x80 },
> + { INTEL_FAM6_KABYLAKE_MOBILE, 0x0A, 0x80 },
> + { INTEL_FAM6_KABYLAKE_MOBILE, 0x09, 0x80 },
> + { INTEL_FAM6_KABYLAKE_DESKTOP, 0x09, 0x80 },
> + { INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003C },
> + { INTEL_FAM6_SKYLAKE_MOBILE, 0x03, 0x000000C2 },
> + { INTEL_FAM6_SKYLAKE_DESKTOP, 0x03, 0x000000C2 },
> + { INTEL_FAM6_BROADWELL_CORE, 0x04, 0x28 },
> + { INTEL_FAM6_BROADWELL_GT3E, 0x01, 0x0000001B },
> + { INTEL_FAM6_HASWELL_ULT, 0x01, 0x21 },
> + { INTEL_FAM6_HASWELL_GT3E, 0x01, 0x18 },
> + { INTEL_FAM6_HASWELL_CORE, 0x03, 0x23 },
> + { INTEL_FAM6_IVYBRIDGE_X, 0x04, 0x42a },
> + { INTEL_FAM6_HASWELL_X, 0x02, 0x3b },
> + { INTEL_FAM6_HASWELL_X, 0x04, 0x10 },
> + { INTEL_FAM6_HASWELL_CORE, 0x03, 0x23 },
> + { INTEL_FAM6_BROADWELL_XEON_D, 0x02, 0x14 },
> + { INTEL_FAM6_BROADWELL_XEON_D, 0x03, 0x7000011 },
> + { INTEL_FAM6_BROADWELL_GT3E, 0x01, 0x0000001B },
> + /* For 406F1 Intel says "0x25, 0x23" while VMware says 0x0B000025
> +  * and a real CPU has a firmware in the 0x0B0000xx range. So: */
> + { INTEL_FAM6_BROADWELL_X, 0x01, 0x0b000025 },
> + { INTEL_FAM6_KABYLAKE_DESKTOP, 0x09, 0x80 },
> + { INTEL_FAM6_SKYLAKE_X, 0x03, 0x100013e },
> + { INTEL_FAM6_SKYLAKE_X, 0x04, 0x200003c },
> +};

Typically tglx likes to use x86_match_cpu() for these things; see also
commit: bd9240a18edfb ("x86/apic: Add TSC_DEADLINE quirk due to
errata").

> +
> +static int bad_spectre_microcode(struct cpuinfo_x86 *c)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) {
> + if (c->x86_model == spectre_bad_microcodes[i].model &&
> +     c->x86_mask == spectre_bad_microcodes[i].stepping)
> + return (c->microcode <= spectre_bad_microcodes[i].microcode);
> + }
> + return 0;
> +}

The above is Intel only, you should check vendor too I think.

>  static void early_init_intel(struct cpuinfo_x86 *c)
>  {
>   u64 misc_enable;
> @@ -122,6 +173,18 @@ static void early_init_intel(struct cpuinfo_x86 *c)
>   if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
>   c->microcode = intel_get_microcode_revision();
>  
> + if ((cpu_has(c, X86_FEATURE_SPEC_CTRL) ||
> +      cpu_has(c, X86_FEATURE_AMD_SPEC_CTRL) ||
> +      cpu_has(c, X86_FEATURE_AMD_PRED_CMD) ||
> +      cpu_has(c, X86_FEATURE_AMD_STIBP)) && bad_spectre_microcode(c)) {
> + pr_warn("Intel Spectre v2 broken microcode detected; disabling SPEC_CTRL\n");
> + clear_cpu_cap(c, X86_FEATURE_SPEC_CTRL);
> + clear_cpu_cap(c, X86_FEATURE_STIBP);
> + clear_cpu_cap(c, X86_FEATURE_AMD_SPEC_CTRL);
> + clear_cpu_cap(c, X86_FEATURE_AMD_PRED_CMD);
> + clear_cpu_cap(c, X86_FEATURE_AMD_STIBP);
> + }

And since its Intel only, what are those AMD features doing there?