aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHuang, Ying <ying.huang@intel.com>2008-01-30 07:34:04 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:34:04 -0500
commit4c881ca1819da180b047f87eedeb9a5957918705 (patch)
tree0181936dae49d098e98f629344ace9ad1daa15c9 /arch
parent8192206df093e8fc607b5072ce71a930d44f8638 (diff)
x86: fix NX bit handling in change_page_attr()
This patch fixes a bug of change_page_attr/change_page_attr_addr on Intel i386/x86_64 CPUs. After changing page attribute to be executable with these functions, the page remains un-executable on Intel i386/x86_64 CPU. Because on Intel i386/x86_64 CPU, only if the "NX" bits of all three level page tables are cleared (PAE is enabled), the corresponding page is executable (refer to section 4.13.2 of Intel 64 and IA-32 Architectures Software Developer's Manual). So, the bug is fixed through clearing the "NX" bit of PMD when splitting the huge PMD. Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/mm/pageattr.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index d18c41d752f3..cbe8e9223bee 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -130,8 +130,13 @@ static int split_large_page(pte_t *kpte, unsigned long address)
130 set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, ref_prot)); 130 set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, ref_prot));
131 131
132 /* 132 /*
133 * Install the new, split up pagetable: 133 * Install the new, split up pagetable. Important detail here:
134 *
135 * On Intel the NX bit of all levels must be cleared to make a
136 * page executable. See section 4.13.2 of Intel 64 and IA-32
137 * Architectures Software Developer's Manual).
134 */ 138 */
139 ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
135 __set_pmd_pte(kpte, address, mk_pte(base, ref_prot)); 140 __set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
136 base = NULL; 141 base = NULL;
137 142