From: Konrad Rzeszutek Wilk Date: Thu, 1 Feb 2018 15:13:37 +0000 (-0500) Subject: x86/spectre_v2: Figure out when to use IBRS. X-Git-Tag: v4.1.12-124.31.3~1187 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f1bb328815e537d76b7070aa71030568e01c74e9;p=users%2Fjedix%2Flinux-maple.git x86/spectre_v2: Figure out when to use IBRS. Which is if: a) on the bootline you have 'spectre_v2=ibrs' _and_ the microcode is loaded that exposes this. And nobody used 'noibrs'. Also if you have 'spectre_v2=ibrs noibrs' we end up falling in the 'lfence'. Unless somebody did 'spectre_v2=ibrs noibrs nolfence', then we go back to automatic discovery. b) Kernel compiled without retpoline and the microcode is available. c) Kernel compiled without retpoline and there is no microcode with IBRS then we pick 'lfence' on system calls. Orabug: 27477743 CVE: CVE-2017-5715 Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: Darren Kenny Reviewed-by: Pavel Tatashin --- diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index fe48aeee79d1..fe7b177028d4 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -110,6 +110,7 @@ enum spectre_v2_mitigation { SPECTRE_V2_RETPOLINE_GENERIC, SPECTRE_V2_RETPOLINE_AMD, SPECTRE_V2_IBRS, + SPECTRE_V2_IBRS_LFENCE, }; #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/cpu/bugs_64.c b/arch/x86/kernel/cpu/bugs_64.c index 67902acff653..a29da6f43a1e 100644 --- a/arch/x86/kernel/cpu/bugs_64.c +++ b/arch/x86/kernel/cpu/bugs_64.c @@ -85,6 +85,7 @@ static const char *spectre_v2_strings[] = { [SPECTRE_V2_RETPOLINE_GENERIC] = "Mitigation: Full generic retpoline", [SPECTRE_V2_RETPOLINE_AMD] = "Mitigation: Full AMD retpoline", [SPECTRE_V2_IBRS] = "Mitigation: IBRS", + [SPECTRE_V2_IBRS_LFENCE] = "Mitigation: lfence", }; @@ -169,6 +170,29 @@ disable: return SPECTRE_V2_CMD_NONE; } +static enum spectre_v2_mitigation __init ibrs_select(void) +{ + enum spectre_v2_mitigation mode = SPECTRE_V2_NONE; + + /* If it is ON, OK, lets use it.*/ + if (check_ibrs_inuse()) + mode = SPECTRE_V2_IBRS; + else { + /* + * If that didn't work (say no microcode or noibrs), we end up using + * lfence on system calls/exceptions/parameters. + */ + if (lfence_inuse) + mode = SPECTRE_V2_IBRS_LFENCE; + } + + if (mode == SPECTRE_V2_NONE) + /* Well, fallback on automatic discovery. */ + pr_info("IBRS and lfence could not be enabled.\n"); + + return mode; +} + static void __init spectre_v2_select_mitigation(void) { enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); @@ -211,7 +235,10 @@ static void __init spectre_v2_select_mitigation(void) goto retpoline_auto; break; case SPECTRE_V2_CMD_IBRS: - mode = SPECTRE_V2_IBRS; + mode = ibrs_select(); + if (mode == SPECTRE_V2_NONE) + goto retpoline_auto; + goto display; break; /* Not needed but compilers may complain otherwise. */ } @@ -227,12 +254,19 @@ retpoline_auto: } mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD : SPECTRE_V2_RETPOLINE_MINIMAL_AMD; + /* On AMD we do not need IBRS, so lets use the ASM mitigation. */ setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD); setup_force_cpu_cap(X86_FEATURE_RETPOLINE); } else { retpoline_generic: mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC : SPECTRE_V2_RETPOLINE_MINIMAL; + + /* IBRS available. Lets see if we are compiled with retpoline. */ + if (check_ibrs_inuse() && !retp_compiler()) { + mode = SPECTRE_V2_IBRS; + goto display; + } setup_force_cpu_cap(X86_FEATURE_RETPOLINE); } display: @@ -243,6 +277,7 @@ display: if (mode == SPECTRE_V2_RETPOLINE_GENERIC || mode == SPECTRE_V2_RETPOLINE_AMD) { set_ibrs_disabled(); + set_ipbp_disabled(); set_lfence_disabled(); } }