summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-09-21 19:43:13 (GMT)
committerH. Peter Anvin <hpa@linux.intel.com>2012-09-21 19:45:27 (GMT)
commit52b6179ac87d33c2eeaff5292786a10fe98cff64 (patch)
tree6ec59d41c4840844031c5030c6fbbd4cdd40819d /arch
parent63bcff2a307b9bcc712a8251eb27df8b2e117967 (diff)
downloadlinux-52b6179ac87d33c2eeaff5292786a10fe98cff64.tar.xz
x86, smap: Turn on Supervisor Mode Access Prevention
If Supervisor Mode Access Prevention is available and not disabled by the user, turn it on. Also fix the expansion of SMEP (Supervisor Mode Execution Prevention.) Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Link: http://lkml.kernel.org/r/1348256595-29119-10-git-send-email-hpa@linux.intel.com
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/cpu/common.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index cd43e52..7d35d65 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -278,6 +278,31 @@ static __cpuinit void setup_smep(struct cpuinfo_x86 *c)
}
}
+static int disable_smap __cpuinitdata;
+static __init int setup_disable_smap(char *arg)
+{
+ disable_smap = 1;
+ return 1;
+}
+__setup("nosmap", setup_disable_smap);
+
+static __cpuinit void setup_smap(struct cpuinfo_x86 *c)
+{
+ if (cpu_has(c, X86_FEATURE_SMAP)) {
+ if (unlikely(disable_smap)) {
+ setup_clear_cpu_cap(X86_FEATURE_SMAP);
+ clear_in_cr4(X86_CR4_SMAP);
+ } else {
+ set_in_cr4(X86_CR4_SMAP);
+ /*
+ * Don't use clac() here since alternatives
+ * haven't run yet...
+ */
+ asm volatile(__stringify(__ASM_CLAC) ::: "memory");
+ }
+ }
+}
+
/*
* Some CPU features depend on higher CPUID levels, which may not always
* be available due to CPUID level capping or broken virtualization
@@ -713,6 +738,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
filter_cpuid_features(c, false);
setup_smep(c);
+ setup_smap(c);
if (this_cpu->c_bsp_init)
this_cpu->c_bsp_init(c);