diff options
| -rw-r--r-- | arch/x86/include/asm/pgtable_types.h | 1 | ||||
| -rw-r--r-- | arch/x86/mm/Makefile | 4 | ||||
| -rw-r--r-- | arch/x86/mm/init.c | 63 | ||||
| -rw-r--r-- | arch/x86/mm/setup_nx.c | 69 |
4 files changed, 72 insertions, 65 deletions
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 54cb697f4900..e9918d99f83c 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h | |||
| @@ -277,6 +277,7 @@ static inline pteval_t pte_flags(pte_t pte) | |||
| 277 | typedef struct page *pgtable_t; | 277 | typedef struct page *pgtable_t; |
| 278 | 278 | ||
| 279 | extern pteval_t __supported_pte_mask; | 279 | extern pteval_t __supported_pte_mask; |
| 280 | extern void set_nx(void); | ||
| 280 | extern int nx_enabled; | 281 | extern int nx_enabled; |
| 281 | 282 | ||
| 282 | #define pgprot_writecombine pgprot_writecombine | 283 | #define pgprot_writecombine pgprot_writecombine |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index dd313d035de7..06630d26e56d 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | obj-y := init.o init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ | 1 | obj-y := init.o init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ |
| 2 | pat.o pgtable.o physaddr.o gup.o | 2 | pat.o pgtable.o physaddr.o gup.o setup_nx.o |
| 3 | 3 | ||
| 4 | # Make sure __phys_addr has no stackprotector | 4 | # Make sure __phys_addr has no stackprotector |
| 5 | nostackp := $(call cc-option, -fno-stack-protector) | 5 | nostackp := $(call cc-option, -fno-stack-protector) |
| 6 | CFLAGS_physaddr.o := $(nostackp) | 6 | CFLAGS_physaddr.o := $(nostackp) |
| 7 | CFLAGS_init.o := $(nostackp) | 7 | CFLAGS_setup_nx.o := $(nostackp) |
| 8 | 8 | ||
| 9 | obj-$(CONFIG_SMP) += tlb.o | 9 | obj-$(CONFIG_SMP) += tlb.o |
| 10 | 10 | ||
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 0607119cef94..73ffd5536f62 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
| @@ -28,69 +28,6 @@ int direct_gbpages | |||
| 28 | #endif | 28 | #endif |
| 29 | ; | 29 | ; |
| 30 | 30 | ||
| 31 | int nx_enabled; | ||
| 32 | |||
| 33 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | ||
| 34 | static int disable_nx __cpuinitdata; | ||
| 35 | |||
| 36 | /* | ||
| 37 | * noexec = on|off | ||
| 38 | * | ||
| 39 | * Control non-executable mappings for processes. | ||
| 40 | * | ||
| 41 | * on Enable | ||
| 42 | * off Disable | ||
| 43 | */ | ||
| 44 | static int __init noexec_setup(char *str) | ||
| 45 | { | ||
| 46 | if (!str) | ||
| 47 | return -EINVAL; | ||
| 48 | if (!strncmp(str, "on", 2)) { | ||
| 49 | __supported_pte_mask |= _PAGE_NX; | ||
| 50 | disable_nx = 0; | ||
| 51 | } else if (!strncmp(str, "off", 3)) { | ||
| 52 | disable_nx = 1; | ||
| 53 | __supported_pte_mask &= ~_PAGE_NX; | ||
| 54 | } | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | early_param("noexec", noexec_setup); | ||
| 58 | #endif | ||
| 59 | |||
| 60 | #ifdef CONFIG_X86_PAE | ||
| 61 | static void __init set_nx(void) | ||
| 62 | { | ||
| 63 | unsigned int v[4], l, h; | ||
| 64 | |||
| 65 | if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) { | ||
| 66 | cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]); | ||
| 67 | |||
| 68 | if ((v[3] & (1 << 20)) && !disable_nx) { | ||
| 69 | rdmsr(MSR_EFER, l, h); | ||
| 70 | l |= EFER_NX; | ||
| 71 | wrmsr(MSR_EFER, l, h); | ||
| 72 | nx_enabled = 1; | ||
| 73 | __supported_pte_mask |= _PAGE_NX; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | ||
| 77 | #else | ||
| 78 | static inline void set_nx(void) | ||
| 79 | { | ||
| 80 | } | ||
| 81 | #endif | ||
| 82 | |||
| 83 | #ifdef CONFIG_X86_64 | ||
| 84 | void __cpuinit check_efer(void) | ||
| 85 | { | ||
| 86 | unsigned long efer; | ||
| 87 | |||
| 88 | rdmsrl(MSR_EFER, efer); | ||
| 89 | if (!(efer & EFER_NX) || disable_nx) | ||
| 90 | __supported_pte_mask &= ~_PAGE_NX; | ||
| 91 | } | ||
| 92 | #endif | ||
| 93 | |||
| 94 | static void __init find_early_table_space(unsigned long end, int use_pse, | 31 | static void __init find_early_table_space(unsigned long end, int use_pse, |
| 95 | int use_gbpages) | 32 | int use_gbpages) |
| 96 | { | 33 | { |
diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c new file mode 100644 index 000000000000..513d8ed5d2ec --- /dev/null +++ b/arch/x86/mm/setup_nx.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | #include <linux/spinlock.h> | ||
| 2 | #include <linux/errno.h> | ||
| 3 | #include <linux/init.h> | ||
| 4 | |||
| 5 | #include <asm/pgtable.h> | ||
| 6 | |||
| 7 | int nx_enabled; | ||
| 8 | |||
| 9 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | ||
| 10 | static int disable_nx __cpuinitdata; | ||
| 11 | |||
| 12 | /* | ||
| 13 | * noexec = on|off | ||
| 14 | * | ||
| 15 | * Control non-executable mappings for processes. | ||
| 16 | * | ||
| 17 | * on Enable | ||
| 18 | * off Disable | ||
| 19 | */ | ||
| 20 | static int __init noexec_setup(char *str) | ||
| 21 | { | ||
| 22 | if (!str) | ||
| 23 | return -EINVAL; | ||
| 24 | if (!strncmp(str, "on", 2)) { | ||
| 25 | __supported_pte_mask |= _PAGE_NX; | ||
| 26 | disable_nx = 0; | ||
| 27 | } else if (!strncmp(str, "off", 3)) { | ||
| 28 | disable_nx = 1; | ||
| 29 | __supported_pte_mask &= ~_PAGE_NX; | ||
| 30 | } | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | 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 | |||
| 59 | #ifdef CONFIG_X86_64 | ||
| 60 | void __cpuinit check_efer(void) | ||
| 61 | { | ||
| 62 | unsigned long efer; | ||
| 63 | |||
| 64 | rdmsrl(MSR_EFER, efer); | ||
| 65 | if (!(efer & EFER_NX) || disable_nx) | ||
| 66 | __supported_pte_mask &= ~_PAGE_NX; | ||
| 67 | } | ||
| 68 | #endif | ||
| 69 | |||
