]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ARM: Add support for checking access permissions on prefetch aborts
authorRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 20 Sep 2009 12:18:47 +0000 (13:18 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 20 Sep 2009 15:53:40 +0000 (16:53 +0100)
ARMv6 introduces non-executable mappings, which can cause prefetch aborts
when an attempt is made to execute from such a mapping.  Currently, this
causes us to loop in the page fault handler since we don't correctly
check for proper permissions.

Fix this by checking that VMAs have VM_EXEC set for prefetch aborts.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mm/fault.c

index b7ce07d416cd1b825d6d44bf90ba3d7e162d1a1c..379f7855605554c9ae955cf7ffe44964374f297e 100644 (file)
@@ -26,8 +26,9 @@
 #include "fault.h"
 
 /*
- * Fault status register encodings
+ * Fault status register encodings.  We steal bit 31 for our own purposes.
  */
+#define FSR_LNX_PF             (1 << 31)
 #define FSR_WRITE              (1 << 11)
 #define FSR_FS4                        (1 << 10)
 #define FSR_FS3_0              (15)
@@ -205,6 +206,8 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
 
        if (fsr & FSR_WRITE)
                mask = VM_WRITE;
+       if (fsr & FSR_LNX_PF)
+               mask = VM_EXEC;
 
        return vma->vm_flags & mask ? false : true;
 }
@@ -503,7 +506,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
        struct siginfo info;
 
-       if (!inf->fn(addr, fsr, regs))
+       if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
                return;
 
        printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
@@ -519,6 +522,6 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 asmlinkage void __exception
 do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
 {
-       do_translation_fault(addr, 0, regs);
+       do_translation_fault(addr, FSR_LNX_PF, regs);
 }