]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
x86/spectre_v2: Figure out when to use IBRS.
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 1 Feb 2018 15:13:37 +0000 (10:13 -0500)
committerJack Vogel <jack.vogel@oracle.com>
Wed, 7 Feb 2018 19:00:41 +0000 (11:00 -0800)
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 <konrad.wilk@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Pavel Tatashin <pasha.tatashin@oracle.com>
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/cpu/bugs_64.c

index fe48aeee79d1ebf5e370d3ea966c3f49cfe6f820..fe7b177028d4ccf23e598a9611aeb281d8453fd3 100644 (file)
@@ -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__ */
index 67902acff653e0ff976a7de5d016c8a8f3a72030..a29da6f43a1eefdf9e5e17cd7e74f0fba5ef6fe9 100644 (file)
@@ -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();
        }
 }