Skip to content

Commit 890c306

Browse files
committed
x86/bugs: Workaround for incorrectly set X86_BUG_RETBLEED under VMware
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2189577 Upstream Status: RHEL only It is found that VMware hypervisor may incorrectly set the ARCH_CAP_RSBA bit (RET may use alternative branch predictors) of the MSR_IA32_ARCH_CAPABILITIES MSR on some older Intel processors like Haswell which is not affected by RETBleed. This causes the RHEL kernel to think that the processor is vulnerable to RETBleed and hence sets X86_BUG_RETBLEED. This has the side effect of forcing the use of IBRS as Spectre v2 mitigation for processors that have it which can have a significant performance impact. Since it is known that Intel CPUs before Skylake are not speculative enough to be susceptible to RETBleed, we can work around this VMware issue by putting some of the Intel CPUs before Skylake (Westmere, SandyBridge, IvyBridge, Haswell, Broadwell) in a new whitelist and checking that list before setting X86_BUG_RETBLEED. For other hypervisors or bare metal that does not have the bug, the new code will not be activated on those older Intel processors since the ARCH_CAP_RSBA bit should not be set. Signed-off-by: Waiman Long <longman@redhat.com>
1 parent 4bf5934 commit 890c306

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

arch/x86/kernel/cpu/common.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,37 @@ void __init setup_cpu_local_masks(void)
176176
alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
177177
}
178178

179+
/*
180+
* It is known that Intel family 6 CPUs before Skylake are not vulnerable
181+
* to Retbleed.
182+
*/
183+
static const bool cpu_in_retbleed_whitelist(struct cpuinfo_x86 *c)
184+
{
185+
static const bool retbleed_whitelist[] = {
186+
[INTEL_FAM6_WESTMERE] = true,
187+
[INTEL_FAM6_WESTMERE_EP] = true,
188+
[INTEL_FAM6_WESTMERE_EX] = true,
189+
[INTEL_FAM6_SANDYBRIDGE] = true,
190+
[INTEL_FAM6_SANDYBRIDGE_X] = true,
191+
[INTEL_FAM6_IVYBRIDGE] = true,
192+
[INTEL_FAM6_IVYBRIDGE_X] = true,
193+
[INTEL_FAM6_HASWELL] = true,
194+
[INTEL_FAM6_HASWELL_X] = true,
195+
[INTEL_FAM6_HASWELL_L] = true,
196+
[INTEL_FAM6_HASWELL_G] = true,
197+
[INTEL_FAM6_BROADWELL] = true,
198+
[INTEL_FAM6_BROADWELL_G] = true,
199+
[INTEL_FAM6_BROADWELL_X] = true,
200+
[INTEL_FAM6_BROADWELL_D] = true,
201+
};
202+
203+
if ((c->x86_vendor != X86_VENDOR_INTEL) || (c->x86 != 6) ||
204+
(c->x86_model >= ARRAY_SIZE(retbleed_whitelist)))
205+
return false;
206+
else
207+
return retbleed_whitelist[c->x86_model];
208+
}
209+
179210
static void default_init(struct cpuinfo_x86 *c)
180211
{
181212
#ifdef CONFIG_X86_64
@@ -1414,7 +1445,8 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
14141445
}
14151446

14161447
if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
1417-
if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
1448+
if (cpu_matches(cpu_vuln_blacklist, RETBLEED) ||
1449+
((ia32_cap & ARCH_CAP_RSBA) && !cpu_in_retbleed_whitelist(c)))
14181450
setup_force_cpu_bug(X86_BUG_RETBLEED);
14191451
}
14201452

0 commit comments

Comments
 (0)