summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.davemloft.net>2004-06-30 10:38:22 -0700
committerDavid S. Miller <davem@nuts.davemloft.net>2004-06-30 10:38:22 -0700
commit21f4cfbb029f12f5fc2d77a576af5ce8fb6c429c (patch)
treedf629a401224b844575e2c15e22e20c64b52313c
parentb46041d99bbdf366b61c44ac9ded5dd5536a265a (diff)
[SPARC64]: Non-executable page support.
Based upon the PAX patches. Credit to PaX Team <pageexec@freemail.hu> Signed-off-by: David S. Miller <davem@redhat.com>
-rw-r--r--arch/sparc64/kernel/itlb_base.S6
-rw-r--r--arch/sparc64/mm/fault.c12
-rw-r--r--include/asm-sparc64/pgtable.h31
3 files changed, 35 insertions, 14 deletions
diff --git a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S
index 36c41501a344..b5e32dfa4fbc 100644
--- a/arch/sparc64/kernel/itlb_base.S
+++ b/arch/sparc64/kernel/itlb_base.S
@@ -41,6 +41,9 @@
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE
1: brgez,pn %g5, 3f ! Not valid, branch out
+ sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot
+ andcc %g5, %g4, %g0 ! Executable?
+ be,pn %xcc, 3f ! Nope, branch.
nop ! Delay-slot
2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB
retry ! Trap return
@@ -73,9 +76,6 @@ winfix_trampoline:
nop
nop
nop
- nop
- nop
- nop
CREATE_VPTE_NOP
#undef CREATE_VPTE_OFFSET1
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 5fc4644aad99..ac57b9e7960d 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -257,7 +257,7 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
* in that case.
*/
- if (!(fault_code & FAULT_CODE_WRITE) &&
+ if (!(fault_code & (FAULT_CODE_WRITE|FAULT_CODE_ITLB)) &&
(insn & 0xc0800000) == 0xc0800000) {
if (insn & 0x2000)
asi = (regs->tstate >> 24);
@@ -408,6 +408,16 @@ continue_fault:
*/
good_area:
si_code = SEGV_ACCERR;
+
+ /* If we took a ITLB miss on a non-executable page, catch
+ * that here.
+ */
+ if ((fault_code & FAULT_CODE_ITLB) && !(vma->vm_flags & VM_EXEC)) {
+ BUG_ON(address != regs->tpc);
+ BUG_ON(regs->tstate & TSTATE_PRIV);
+ goto bad_area;
+ }
+
if (fault_code & FAULT_CODE_WRITE) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 505db07e2554..e3d4f6575a0e 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -180,16 +180,27 @@
/* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */
#define PAGE_SHARED __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
- __ACCESS_BITS | _PAGE_WRITE)
+ __ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC)
#define PAGE_COPY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
- __ACCESS_BITS)
+ __ACCESS_BITS | _PAGE_EXEC)
#define PAGE_READONLY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
- __ACCESS_BITS)
+ __ACCESS_BITS | _PAGE_EXEC)
#define PAGE_KERNEL __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
- __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS)
+ __PRIV_BITS | \
+ __ACCESS_BITS | __DIRTY_BITS | _PAGE_EXEC)
+
+#define PAGE_SHARED_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
+ _PAGE_CACHE | \
+ __ACCESS_BITS | _PAGE_WRITE)
+
+#define PAGE_COPY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
+ _PAGE_CACHE | __ACCESS_BITS)
+
+#define PAGE_READONLY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
+ _PAGE_CACHE | __ACCESS_BITS)
#define _PFN_MASK _PAGE_PADDR
@@ -197,18 +208,18 @@
__ACCESS_BITS | _PAGE_E)
#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
+#define __P001 PAGE_READONLY_NOEXEC
+#define __P010 PAGE_COPY_NOEXEC
+#define __P011 PAGE_COPY_NOEXEC
#define __P100 PAGE_READONLY
#define __P101 PAGE_READONLY
#define __P110 PAGE_COPY
#define __P111 PAGE_COPY
#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
+#define __S001 PAGE_READONLY_NOEXEC
+#define __S010 PAGE_SHARED_NOEXEC
+#define __S011 PAGE_SHARED_NOEXEC
#define __S100 PAGE_READONLY
#define __S101 PAGE_READONLY
#define __S110 PAGE_SHARED