diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-11-13 18:28:16 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-11-16 16:44:59 -0500 |
commit | 4763ed4d45522b876c97e1f7f4b659d211f75571 (patch) | |
tree | ae053500de9f1c374e4b7f34d8f21d45a5b961d2 /arch/x86 | |
parent | 583140afb989f24d115e80be5c91e503b58ccfc0 (diff) |
x86, mm: Clean up and simplify NX enablement
The 32- and 64-bit code used very different mechanisms for enabling
NX, but even the 32-bit code was enabling NX in head_32.S if it is
available. Furthermore, we had a bewildering collection of tests for
the available of NX.
This patch:
a) merges the 32-bit set_nx() and the 64-bit check_efer() function
into a single x86_configure_nx() function. EFER control is left
to the head code.
b) eliminates the nx_enabled variable entirely. Things that need to
test for NX enablement can verify __supported_pte_mask directly,
and cpu_has_nx gives the supported status of NX.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Vegard Nossum <vegardno@ifi.uio.no>
Cc: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: Chris Wright <chrisw@sous-sol.org>
LKML-Reference: <1258154897-6770-5-git-send-email-hpa@zytor.com>
Acked-by: Kees Cook <kees.cook@canonical.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/proto.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 8 | ||||
-rw-r--r-- | arch/x86/mm/init.c | 4 | ||||
-rw-r--r-- | arch/x86/mm/setup_nx.c | 43 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 4 |
6 files changed, 13 insertions, 50 deletions
diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index 621f56d73121..add7f18f17a7 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h | |||
@@ -16,7 +16,7 @@ extern void ia32_sysenter_target(void); | |||
16 | 16 | ||
17 | extern void syscall32_cpu_init(void); | 17 | extern void syscall32_cpu_init(void); |
18 | 18 | ||
19 | extern void check_efer(void); | 19 | extern void x86_configure_nx(void); |
20 | 20 | ||
21 | extern int reboot_force; | 21 | extern int reboot_force; |
22 | 22 | ||
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cc25c2b4a567..18346da8c594 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1136,7 +1136,7 @@ void __cpuinit cpu_init(void) | |||
1136 | wrmsrl(MSR_KERNEL_GS_BASE, 0); | 1136 | wrmsrl(MSR_KERNEL_GS_BASE, 0); |
1137 | barrier(); | 1137 | barrier(); |
1138 | 1138 | ||
1139 | check_efer(); | 1139 | x86_configure_nx(); |
1140 | if (cpu != 0) | 1140 | if (cpu != 0) |
1141 | enable_x2apic(); | 1141 | enable_x2apic(); |
1142 | 1142 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 0a6e94ab8339..23b7f46bf843 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -787,21 +787,17 @@ void __init setup_arch(char **cmdline_p) | |||
787 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); | 787 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); |
788 | *cmdline_p = command_line; | 788 | *cmdline_p = command_line; |
789 | 789 | ||
790 | #ifdef CONFIG_X86_64 | ||
791 | /* | 790 | /* |
792 | * Must call this twice: Once just to detect whether hardware doesn't | 791 | * Must call this twice: Once just to detect whether hardware doesn't |
793 | * support NX (so that the early EHCI debug console setup can safely | 792 | * support NX (so that the early EHCI debug console setup can safely |
794 | * call set_fixmap(), and then again after parsing early parameters to | 793 | * call set_fixmap(), and then again after parsing early parameters to |
795 | * honor the respective command line option. | 794 | * honor the respective command line option. |
796 | */ | 795 | */ |
797 | check_efer(); | 796 | x86_configure_nx(); |
798 | #endif | ||
799 | 797 | ||
800 | parse_early_param(); | 798 | parse_early_param(); |
801 | 799 | ||
802 | #ifdef CONFIG_X86_64 | 800 | x86_configure_nx(); |
803 | check_efer(); | ||
804 | #endif | ||
805 | 801 | ||
806 | /* Must be before kernel pagetables are setup */ | 802 | /* Must be before kernel pagetables are setup */ |
807 | vmi_activate(); | 803 | vmi_activate(); |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 73ffd5536f62..27ec2c23fd47 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -146,8 +146,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
146 | use_gbpages = direct_gbpages; | 146 | use_gbpages = direct_gbpages; |
147 | #endif | 147 | #endif |
148 | 148 | ||
149 | set_nx(); | 149 | /* XXX: replace this with Kees' improved messages */ |
150 | if (nx_enabled) | 150 | if (__supported_pte_mask & _PAGE_NX) |
151 | printk(KERN_INFO "NX (Execute Disable) protection: active\n"); | 151 | printk(KERN_INFO "NX (Execute Disable) protection: active\n"); |
152 | 152 | ||
153 | /* Enable PSE if available */ | 153 | /* Enable PSE if available */ |
diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 513d8ed5d2ec..355818b087b5 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c | |||
@@ -3,10 +3,8 @@ | |||
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | 4 | ||
5 | #include <asm/pgtable.h> | 5 | #include <asm/pgtable.h> |
6 | #include <asm/proto.h> | ||
6 | 7 | ||
7 | int nx_enabled; | ||
8 | |||
9 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | ||
10 | static int disable_nx __cpuinitdata; | 8 | static int disable_nx __cpuinitdata; |
11 | 9 | ||
12 | /* | 10 | /* |
@@ -22,48 +20,19 @@ static int __init noexec_setup(char *str) | |||
22 | if (!str) | 20 | if (!str) |
23 | return -EINVAL; | 21 | return -EINVAL; |
24 | if (!strncmp(str, "on", 2)) { | 22 | if (!strncmp(str, "on", 2)) { |
25 | __supported_pte_mask |= _PAGE_NX; | ||
26 | disable_nx = 0; | 23 | disable_nx = 0; |
27 | } else if (!strncmp(str, "off", 3)) { | 24 | } else if (!strncmp(str, "off", 3)) { |
28 | disable_nx = 1; | 25 | disable_nx = 1; |
29 | __supported_pte_mask &= ~_PAGE_NX; | ||
30 | } | 26 | } |
27 | x86_configure_nx(); | ||
31 | return 0; | 28 | return 0; |
32 | } | 29 | } |
33 | early_param("noexec", noexec_setup); | 30 | early_param("noexec", noexec_setup); |
34 | #endif | ||
35 | |||
36 | #ifdef CONFIG_X86_PAE | ||
37 | void __init set_nx(void) | ||
38 | { | ||
39 | unsigned int v[4], l, h; | ||
40 | |||
41 | if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) { | ||
42 | cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]); | ||
43 | |||
44 | if ((v[3] & (1 << 20)) && !disable_nx) { | ||
45 | rdmsr(MSR_EFER, l, h); | ||
46 | l |= EFER_NX; | ||
47 | wrmsr(MSR_EFER, l, h); | ||
48 | nx_enabled = 1; | ||
49 | __supported_pte_mask |= _PAGE_NX; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | #else | ||
54 | void set_nx(void) | ||
55 | { | ||
56 | } | ||
57 | #endif | ||
58 | 31 | ||
59 | #ifdef CONFIG_X86_64 | 32 | void __cpuinit x86_configure_nx(void) |
60 | void __cpuinit check_efer(void) | ||
61 | { | 33 | { |
62 | unsigned long efer; | 34 | if (cpu_has_nx && !disable_nx) |
63 | 35 | __supported_pte_mask |= _PAGE_NX; | |
64 | rdmsrl(MSR_EFER, efer); | 36 | else |
65 | if (!(efer & EFER_NX) || disable_nx) | ||
66 | __supported_pte_mask &= ~_PAGE_NX; | 37 | __supported_pte_mask &= ~_PAGE_NX; |
67 | } | 38 | } |
68 | #endif | ||
69 | |||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 3439616d69f1..c5e805d4a788 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1082,10 +1082,8 @@ asmlinkage void __init xen_start_kernel(void) | |||
1082 | 1082 | ||
1083 | __supported_pte_mask |= _PAGE_IOMAP; | 1083 | __supported_pte_mask |= _PAGE_IOMAP; |
1084 | 1084 | ||
1085 | #ifdef CONFIG_X86_64 | ||
1086 | /* Work out if we support NX */ | 1085 | /* Work out if we support NX */ |
1087 | check_efer(); | 1086 | x86_configure_nx(); |
1088 | #endif | ||
1089 | 1087 | ||
1090 | xen_setup_features(); | 1088 | xen_setup_features(); |
1091 | 1089 | ||