Skip to content

Commit

Permalink
x86: unify noexec handling
Browse files Browse the repository at this point in the history
This patch unifies noexec handling on 32-bit and 64-bit.

[ Impact: cleanup ]

Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
[ mingo@elte.hu: build fix ]
LKML-Reference: <1240303167.771.69.camel@penberg-laptop>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Pekka Enberg authored and Ingo Molnar committed Apr 21, 2009
1 parent 8ecee46 commit 8938891
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 90 deletions.
1 change: 0 additions & 1 deletion arch/x86/include/asm/pgtable_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,6 @@ typedef struct page *pgtable_t;

extern pteval_t __supported_pte_mask;
extern int nx_enabled;
extern void set_nx(void);

#define pgprot_writecombine pgprot_writecombine
extern pgprot_t pgprot_writecombine(pgprot_t prot);
Expand Down
67 changes: 63 additions & 4 deletions arch/x86/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,69 @@ int direct_gbpages
#endif
;

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
static 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
static inline 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

static void __init find_early_table_space(unsigned long end, int use_pse,
int use_gbpages)
{
Expand Down Expand Up @@ -158,12 +221,9 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
use_gbpages = direct_gbpages;
#endif

#ifdef CONFIG_X86_32
#ifdef CONFIG_X86_PAE
set_nx();
if (nx_enabled)
printk(KERN_INFO "NX (Execute Disable) protection: active\n");
#endif

/* Enable PSE if available */
if (cpu_has_pse)
Expand All @@ -174,7 +234,6 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
set_in_cr4(X86_CR4_PGE);
__supported_pte_mask |= _PAGE_GLOBAL;
}
#endif

if (use_gbpages)
page_size_mask |= 1 << PG_LEVEL_1G;
Expand Down
52 changes: 0 additions & 52 deletions arch/x86/mm/init_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,61 +587,9 @@ void zap_low_mappings(void)
flush_tlb_all();
}

int nx_enabled;

pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
EXPORT_SYMBOL_GPL(__supported_pte_mask);

#ifdef CONFIG_X86_PAE

static int disable_nx __initdata;

/*
* noexec = on|off
*
* Control non executable mappings.
*
* on Enable
* off Disable
*/
static int __init noexec_setup(char *str)
{
if (!str || !strcmp(str, "on")) {
if (cpu_has_nx) {
__supported_pte_mask |= _PAGE_NX;
disable_nx = 0;
}
} else {
if (!strcmp(str, "off")) {
disable_nx = 1;
__supported_pte_mask &= ~_PAGE_NX;
} else {
return -EINVAL;
}
}

return 0;
}
early_param("noexec", noexec_setup);

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;
}
}
}
#endif

/* user-defined highmem size */
static unsigned int highmem_pages = -1;

Expand Down
33 changes: 0 additions & 33 deletions arch/x86/mm/init_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,39 +85,6 @@ early_param("gbpages", parse_direct_gbpages_on);
pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
EXPORT_SYMBOL_GPL(__supported_pte_mask);

static int disable_nx __cpuinitdata;

/*
* noexec=on|off
* Control non-executable mappings for 64-bit processes.
*
* on Enable (default)
* off Disable
*/
static int __init nonx_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", nonx_setup);

void __cpuinit check_efer(void)
{
unsigned long efer;

rdmsrl(MSR_EFER, efer);
if (!(efer & EFER_NX) || disable_nx)
__supported_pte_mask &= ~_PAGE_NX;
}

int force_personality32;

/*
Expand Down

0 comments on commit 8938891

Please sign in to comment.