diff options
author | Fenghua Yu <fenghua.yu@intel.com> | 2011-05-11 19:51:05 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2011-05-18 00:22:00 -0400 |
commit | de5397ad5b9ad22e2401c4dacdf1bb3b19c05679 (patch) | |
tree | e8c612c4f84efe458d8ec3c23f1bfd834f20c0f2 /arch | |
parent | dc23c0bccf5eea171c87b3db285d032b9a5f06c4 (diff) |
x86, cpu: Enable/disable Supervisor Mode Execution Protection
Enable/disable newly documented SMEP (Supervisor Mode Execution Protection) CPU
feature in kernel. CR4.SMEP (bit 20) is 0 at power-on. If the feature is
supported by CPU (X86_FEATURE_SMEP), enable SMEP by setting CR4.SMEP. New kernel
option nosmep disables the feature even if the feature is supported by CPU.
[ hpa: moved the call to setup_smep() until after the vendor-specific
initialization; that ensures that CPUID features are unmasked. We
will still run it before we have userspace (never mind uncontrolled
userspace). ]
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
LKML-Reference: <1305157865-31727-1-git-send-email-fenghua.yu@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 173f3a3fa1a6..cbc70a27430c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -254,6 +254,25 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) | |||
254 | } | 254 | } |
255 | #endif | 255 | #endif |
256 | 256 | ||
257 | static int disable_smep __initdata; | ||
258 | static __init int setup_disable_smep(char *arg) | ||
259 | { | ||
260 | disable_smep = 1; | ||
261 | return 1; | ||
262 | } | ||
263 | __setup("nosmep", setup_disable_smep); | ||
264 | |||
265 | static __init void setup_smep(struct cpuinfo_x86 *c) | ||
266 | { | ||
267 | if (cpu_has(c, X86_FEATURE_SMEP)) { | ||
268 | if (unlikely(disable_smep)) { | ||
269 | setup_clear_cpu_cap(X86_FEATURE_SMEP); | ||
270 | clear_in_cr4(X86_CR4_SMEP); | ||
271 | } else | ||
272 | set_in_cr4(X86_CR4_SMEP); | ||
273 | } | ||
274 | } | ||
275 | |||
257 | /* | 276 | /* |
258 | * Some CPU features depend on higher CPUID levels, which may not always | 277 | * Some CPU features depend on higher CPUID levels, which may not always |
259 | * be available due to CPUID level capping or broken virtualization | 278 | * be available due to CPUID level capping or broken virtualization |
@@ -667,6 +686,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) | |||
667 | c->cpu_index = 0; | 686 | c->cpu_index = 0; |
668 | #endif | 687 | #endif |
669 | filter_cpuid_features(c, false); | 688 | filter_cpuid_features(c, false); |
689 | |||
690 | setup_smep(c); | ||
670 | } | 691 | } |
671 | 692 | ||
672 | void __init early_cpu_init(void) | 693 | void __init early_cpu_init(void) |
@@ -752,6 +773,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | |||
752 | #endif | 773 | #endif |
753 | } | 774 | } |
754 | 775 | ||
776 | setup_smep(c); | ||
777 | |||
755 | get_model_name(c); /* Default name */ | 778 | get_model_name(c); /* Default name */ |
756 | 779 | ||
757 | detect_nopl(c); | 780 | detect_nopl(c); |