From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from aserp2120.oracle.com ([141.146.126.78]) by Galois.linutronix.de with esmtps (TLS1.2:RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1f8ns8-0002bn-MT for speck@linutronix.de; Wed, 18 Apr 2018 16:15:46 +0200 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w3IEBZps184815 for ; Wed, 18 Apr 2018 14:15:38 GMT Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp2120.oracle.com with ESMTP id 2hdrxnausx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Wed, 18 Apr 2018 14:15:38 +0000 Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w3IEFbPE006146 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Wed, 18 Apr 2018 14:15:37 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id w3IEFasx029369 for ; Wed, 18 Apr 2018 14:15:36 GMT Message-Id: <20180413022657.272027065@localhost.localdomain> Date: Thu, 12 Apr 2018 22:26:51 -0400 From: konrad.wilk@oracle.com Subject: [MODERATED] [patch 2/8] [PATCH v1.3.1 2/7] Linux Patch 2 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit To: speck@linutronix.de List-ID: mdd stands for "Memory Disambiguation Disable" and we have two knobs: nomdd mdd=[off,auto,userspace,boot] (We couldn't use 'md' as that is used by multipath). Memory Disambiguation is a feature that contemporary processors have - which is where store and load operations can run in parallel (even for the same address). Eventually when the memory is fetched with the data value will the store (and load) be fixed up and the execution operations re-run through the CPU. Thanks to the nature of this store-load-store operations can run in parallel. The 'mdd' allows the OS to disable this optimization. Some CPUs have a bug where a load may pass an older overlapping store (speculatively of course). By default this feature is enabled hence the parameters are: - auto - if possible will disable memory disambiguation at boot if CPU is vulnerable to speculation attacks using memory disambgiuation.. - boot - disable memory disambiguation at boot. - userspace - disable memory disambiguation when entering userspace, but enable it in the kernel. - off - do not _disable_ memory disambiguation. And as mentioned - some CPU may have memory dismabiguation that does not lead to speculative vulnerabilities - and for those the 'auto' will pick the right choice. Signed-off-by: Konrad Rzeszutek Wilk --- v3: - Wrong array was used when figuring mdd_v4= arguments - If broken microcode found, also disable MD feature. - s/mdd_v4/mdd/ - s/kernel/userpsace/ - Fix up the commit description --- Documentation/admin-guide/kernel-parameters.txt | 11 +++ arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/nospec-branch.h | 6 ++ arch/x86/kernel/cpu/bugs.c | 93 ++++++++++++++++++++++++- arch/x86/kernel/cpu/intel.c | 1 + 5 files changed, 111 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1d1d53f85ddd..2c22ca7e90a6 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2173,6 +2173,15 @@ md= [HW] RAID subsystems devices and level See Documentation/admin-guide/md.rst. + mdd= [X86] Control memory disambiguation disable mitigation. + + auto - kernel detects whether your CPU model is + vulnerable and picks the most appropiate way + userspace - disable memory disambiguation in userspace, + and enable it in the kernel. + boot - disable memory disambiguation all the time (default). + off - do not control memory disambiguation (insecure) + mdacon= [MDA] Format: , Specifies range of consoles to be captured by the MDA. @@ -2647,6 +2656,8 @@ allow data leaks with this option, which is equivalent to spectre_v2=off. + nomdd [X86] Disable all mitigations for the memory disambiguation vulnerability. + noxsave [BUGS=X86] Disables x86 extended register state save and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state. diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 4393c10fcc6f..7490798a70e9 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -333,6 +333,7 @@ #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ +#define X86_FEATURE_MDD (18*32+31) /* Intel Memory Disambiguation Disable. */ /* * BUG word(s) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index f928ad9b143f..2c098a3250eb 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -216,6 +216,12 @@ enum spectre_v2_mitigation { SPECTRE_V2_RETPOLINE_AMD, SPECTRE_V2_IBRS, }; +/* The MD mitigation variants */ +enum md_mitigation { + MD_NONE, + MD_BOOT_ON, + MD_KERNEL_ON, +}; extern char __indirect_thunk_start[]; extern char __indirect_thunk_end[]; diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 79dfc80c4b9c..561cb228605a 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -27,6 +27,7 @@ #include static void __init spectre_v2_select_mitigation(void); +static void __init md_select_mitigation(void); void __init check_bugs(void) { @@ -40,6 +41,8 @@ void __init check_bugs(void) /* Select the proper spectre mitigation before patching alternatives */ spectre_v2_select_mitigation(); + md_select_mitigation(); + #ifdef CONFIG_X86_32 /* * Check whether we are able to run this kernel safely on SMP. @@ -311,6 +314,94 @@ static void __init spectre_v2_select_mitigation(void) } } +#undef pr_fmt +#define pr_fmt(fmt) "MDD: " fmt + +static enum md_mitigation md_mode = MD_NONE; + +/* The kernel command line selection */ +enum md_mitigation_cmd { + MD_CMD_NONE, + MD_CMD_AUTO, + MD_CMD_BOOT_ON, + MD_CMD_KERNEL_ON, +}; + +static const char *md_strings[] = { + [MD_NONE] = "Vulnerable", + [MD_BOOT_ON] = "Mitigation: Memory disambiguation disabled at boot", + [MD_KERNEL_ON] = "Mitigation: Memory disambiguation disabled in userspace", +}; + +static const struct { + const char *option; + enum md_mitigation_cmd cmd; +} md_mitigation_options[] = { + { "off", MD_CMD_NONE }, + { "auto", MD_CMD_AUTO }, + { "boot", MD_CMD_BOOT_ON }, + { "userspace", MD_CMD_KERNEL_ON }, +}; + +static enum md_mitigation_cmd __init md_parse_cmdline(void) +{ + char arg[20]; + int ret, i; + enum md_mitigation_cmd cmd = MD_CMD_AUTO; + + if (cmdline_find_option_bool(boot_command_line, "nomdd")) + return MD_CMD_NONE; + else { + ret = cmdline_find_option(boot_command_line, "mdd", arg, sizeof(arg)); + if (ret < 0) + return MD_CMD_AUTO; + + for (i = 0; i < ARRAY_SIZE(md_mitigation_options); i++) { + if (!match_option(arg, ret, md_mitigation_options[i].option)) + continue; + cmd = md_mitigation_options[i].cmd; + break; + } + + if (i >= ARRAY_SIZE(md_mitigation_options)) { + pr_err("unknown option (%s). Switching to AUTO select\n", arg); + return MD_CMD_AUTO; + } + } + + return cmd; +} + +static void __init md_select_mitigation(void) +{ + enum md_mitigation_cmd cmd = md_parse_cmdline(); + enum md_mitigation mode = MD_NONE; + + if (!boot_cpu_has_bug(X86_BUG_CPU_MD) && + (cmd == MD_CMD_NONE || cmd == MD_CMD_AUTO)) + return; + + switch (cmd) { + case MD_CMD_AUTO: + case MD_CMD_BOOT_ON: + mode = MD_BOOT_ON; + break; + case MD_CMD_KERNEL_ON: + mode = MD_KERNEL_ON; + break; + case MD_CMD_NONE: + break; + } + + if (!boot_cpu_has(X86_FEATURE_MDD)) + return; + + md_mode = mode; + pr_info("%s\n", md_strings[mode]); + + if (mode == MD_NONE) + setup_clear_cpu_cap(X86_FEATURE_MDD); +} #undef pr_fmt #ifdef CONFIG_SYSFS @@ -346,6 +437,6 @@ ssize_t cpu_show_md(struct device *dev, struct device_attribute *attr, char *buf if (!boot_cpu_has_bug(X86_BUG_CPU_MD)) return sprintf(buf, "Not affected\n"); - return sprintf(buf, "Vulnerable\n"); + return sprintf(buf, "%s\n", md_strings[md_mode]); } #endif diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index c3af167d0a70..16ee38d8977a 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -189,6 +189,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) setup_clear_cpu_cap(X86_FEATURE_STIBP); setup_clear_cpu_cap(X86_FEATURE_SPEC_CTRL); setup_clear_cpu_cap(X86_FEATURE_INTEL_STIBP); + setup_clear_cpu_cap(X86_FEATURE_MDD); } /* -- 2.14.3