| #include <linux/spinlock.h> |
| #include <linux/errno.h> |
| #include <linux/init.h> |
| |
| #include <asm/pgtable.h> |
| |
| int nx_enabled; |
| |
| #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) |
| static int disable_nx __cpuinitdata; |
| |
| /* |
| * noexec = on|off |
| * |
| * Control non-executable mappings for processes. |
| * |
| * on Enable |
| * off Disable |
| */ |
| static int __init noexec_setup(char *str) |
| { |
| if (!str) |
| return -EINVAL; |
| if (!strncmp(str, "on", 2)) { |
| __supported_pte_mask |= _PAGE_NX; |
| disable_nx = 0; |
| } else if (!strncmp(str, "off", 3)) { |
| disable_nx = 1; |
| __supported_pte_mask &= ~_PAGE_NX; |
| } |
| return 0; |
| } |
| early_param("noexec", noexec_setup); |
| #endif |
| |
| #ifdef CONFIG_X86_PAE |
| void __init set_nx(void) |
| { |
| unsigned int v[4], l, h; |
| |
| if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) { |
| cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]); |
| |
| if ((v[3] & (1 << 20)) && !disable_nx) { |
| rdmsr(MSR_EFER, l, h); |
| l |= EFER_NX; |
| wrmsr(MSR_EFER, l, h); |
| nx_enabled = 1; |
| __supported_pte_mask |= _PAGE_NX; |
| } |
| } |
| } |
| #else |
| void set_nx(void) |
| { |
| } |
| #endif |
| |
| #ifdef CONFIG_X86_64 |
| void __cpuinit check_efer(void) |
| { |
| unsigned long efer; |
| |
| rdmsrl(MSR_EFER, efer); |
| if (!(efer & EFER_NX) || disable_nx) |
| __supported_pte_mask &= ~_PAGE_NX; |
| } |
| #endif |
| |