ARM: 7408/1: cacheflush: return error to userspace when flushing syscall fails
authorWill Deacon <will.deacon@arm.com>
Fri, 27 Apr 2012 12:08:53 +0000 (13:08 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 2 May 2012 10:12:49 +0000 (11:12 +0100)
The cacheflush syscall can fail for two reasons:

(1) The arguments are invalid (nonsensical address range or no VMA)

(2) The region generates a translation fault on a VIPT or PIPT cache

This patch allows do_cache_op to return an error code to userspace in
the case of the above. The various coherent_user_range implementations
are modified to return 0 in the case of VIVT caches or -EFAULT in the
case of an abort on v6/v7 cores.

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
20 files changed:
arch/arm/include/asm/cacheflush.h
arch/arm/kernel/traps.c
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-mohawk.S

index 1252a2675ca98de725d70add76ba2c39f3e53b08..004c1bc95d2b9082de58e0626134a779705620b6 100644 (file)
@@ -101,7 +101,7 @@ struct cpu_cache_fns {
        void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
 
        void (*coherent_kern_range)(unsigned long, unsigned long);
-       void (*coherent_user_range)(unsigned long, unsigned long);
+       int  (*coherent_user_range)(unsigned long, unsigned long);
        void (*flush_kern_dcache_area)(void *, size_t);
 
        void (*dma_map_area)(const void *, size_t, int);
@@ -142,7 +142,7 @@ extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
-extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
+extern int  __cpuc_coherent_user_range(unsigned long, unsigned long);
 extern void __cpuc_flush_dcache_area(void *, size_t);
 
 /*
index 63d402f75e25c5d2de8a39cabac8b6d76cba1d05..3647170e9a16ba3aa8838218ed99e74dbc5b7c59 100644 (file)
@@ -479,14 +479,14 @@ static int bad_syscall(int n, struct pt_regs *regs)
        return regs->ARM_r0;
 }
 
-static inline void
+static inline int
 do_cache_op(unsigned long start, unsigned long end, int flags)
 {
        struct mm_struct *mm = current->active_mm;
        struct vm_area_struct *vma;
 
        if (end < start || flags)
-               return;
+               return -EINVAL;
 
        down_read(&mm->mmap_sem);
        vma = find_vma(mm, start);
@@ -497,10 +497,10 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
                        end = vma->vm_end;
 
                up_read(&mm->mmap_sem);
-               flush_cache_user_range(start, end);
-               return;
+               return flush_cache_user_range(start, end);
        }
        up_read(&mm->mmap_sem);
+       return -EINVAL;
 }
 
 /*
@@ -546,8 +546,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
         * the specified region).
         */
        case NR(cacheflush):
-               do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
-               return 0;
+               return do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
 
        case NR(usr26):
                if (!(elf_hwcap & HWCAP_26BIT))
index c2301f226100e371e72c46cde695c186a84b240b..52e35f32eefb293589ce6c8ce11b4871cf178c62 100644 (file)
@@ -78,6 +78,7 @@ ENTRY(v3_coherent_kern_range)
  *     - end    - virtual end address
  */
 ENTRY(v3_coherent_user_range)
+       mov     r0, #0
        mov     pc, lr
 
 /*
index fd9bb7addc8d0cb1e6e7ca7014a8a9079b0f9ca1..022135d2b7e4394313e1bad6ad3deb67ab8e4e14 100644 (file)
@@ -88,6 +88,7 @@ ENTRY(v4_coherent_kern_range)
  *     - end    - virtual end address
  */
 ENTRY(v4_coherent_user_range)
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 4f2c14151ccb78b7dcba40ebb826a05f05209a25..8f1eeae340c84b6b948d3ca4a4f0af91250facb3 100644 (file)
@@ -167,9 +167,9 @@ ENTRY(v4wb_coherent_user_range)
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
        blo     1b
-       mov     ip, #0
-       mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
-       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
 
index 4d7b467631cee24bfae1b1acbd0b66f39373bca2..b34a5f908a82345bd6f4c4eb8b20f44f587cad48 100644 (file)
@@ -125,6 +125,7 @@ ENTRY(v4wt_coherent_user_range)
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
        blo     1b
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 74c2e5a33a4d4aa9e0f347e4b45d3959cc9a68fb..4b10760c56d6fe081dd9ab0988119d2378cd9369 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/errno.h>
 #include <asm/unwind.h>
 
 #include "proc-macros.S"
@@ -135,7 +136,6 @@ ENTRY(v6_coherent_user_range)
 1:
  USER( mcr     p15, 0, r0, c7, c10, 1  )       @ clean D line
        add     r0, r0, #CACHE_LINE_SIZE
-2:
        cmp     r0, r1
        blo     1b
 #endif
@@ -154,13 +154,11 @@ ENTRY(v6_coherent_user_range)
 
 /*
  * Fault handling for the cache operation above. If the virtual address in r0
- * isn't mapped, just try the next page.
+ * isn't mapped, fail with -EFAULT.
  */
 9001:
-       mov     r0, r0, lsr #12
-       mov     r0, r0, lsl #12
-       add     r0, r0, #4096
-       b       2b
+       mov     r0, #-EFAULT
+       mov     pc, lr
  UNWIND(.fnend         )
 ENDPROC(v6_coherent_user_range)
 ENDPROC(v6_coherent_kern_range)
index a655d3da386d6c3620a07bc25176163c21a07e15..39e3fb3db80123b1f276f811f8b26921e77564ee 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/errno.h>
 #include <asm/unwind.h>
 
 #include "proc-macros.S"
@@ -198,7 +199,6 @@ ENTRY(v7_coherent_user_range)
        add     r12, r12, r2
        cmp     r12, r1
        blo     2b
-3:
        mov     r0, #0
        ALT_SMP(mcr     p15, 0, r0, c7, c1, 6)  @ invalidate BTB Inner Shareable
        ALT_UP(mcr      p15, 0, r0, c7, c5, 6)  @ invalidate BTB
@@ -208,13 +208,11 @@ ENTRY(v7_coherent_user_range)
 
 /*
  * Fault handling for the cache operation above. If the virtual address in r0
- * isn't mapped, just try the next page.
+ * isn't mapped, fail with -EFAULT.
  */
 9001:
-       mov     r12, r12, lsr #12
-       mov     r12, r12, lsl #12
-       add     r12, r12, #4096
-       b       3b
+       mov     r0, #-EFAULT
+       mov     pc, lr
  UNWIND(.fnend         )
 ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
index 234951345eb3de1d5a806794819ecc437b8ee924..0650bb87c1e3a68feb64f465bf547c2e3de52771 100644 (file)
@@ -241,6 +241,7 @@ ENTRY(arm1020_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index c244b06caac9630679f11403a1f60bc0617799a8..4188478325a6398fbe8ada36c109694b81f177ea 100644 (file)
@@ -235,6 +235,7 @@ ENTRY(arm1020e_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 38fe22efd18fc804951b85c22480dd294e4a4790..33c68824bff0999d6f718eb065f1c5b1daad9cac 100644 (file)
@@ -224,6 +224,7 @@ ENTRY(arm1022_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 3eb9c3c26c75ac7128585e64316ede8f1662b85f..fbc1d5fc24dcd0b5df37e4f508b4ea7fb9c4bafc 100644 (file)
@@ -218,6 +218,7 @@ ENTRY(arm1026_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index cb941ae95f66ee43132cd267e14eba8161a2580c..1a8c138eb8975697b8d15dee01f71ad2e9e5917c 100644 (file)
@@ -210,6 +210,7 @@ ENTRY(arm920_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 4ec0e074dd554898e3d3c3ba8728bafb768346ea..4c44d7e1c3ca214f4debab4538928ef68113bafd 100644 (file)
@@ -212,6 +212,7 @@ ENTRY(arm922_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 9dccd9a365b38c2c7c1261a280d55f4f4e7d5af4..ec5b1180994fb7b01779a8c457737f803f613e75 100644 (file)
@@ -258,6 +258,7 @@ ENTRY(arm925_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 820259b81a1f3d54f93587d0f1d3618688f98549..c31e62c606c0b6eebf5390c2de640a7fb63ad949 100644 (file)
@@ -221,6 +221,7 @@ ENTRY(arm926_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index 9fdc0a1709748ed27ea06e6155f8904338c5b4ac..a613a7dd71465c994f6d57093954d9110aee12e4 100644 (file)
@@ -160,7 +160,7 @@ ENTRY(arm940_coherent_user_range)
  *     - size  - region size
  */
 ENTRY(arm940_flush_kern_dcache_area)
-       mov     ip, #0
+       mov     r0, #0
        mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
 1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
 2:     mcr     p15, 0, r3, c7, c14, 2          @ clean/flush D index
@@ -168,8 +168,8 @@ ENTRY(arm940_flush_kern_dcache_area)
        bcs     2b                              @ entries 63 to 0
        subs    r1, r1, #1 << 4
        bcs     1b                              @ segments 7 to 0
-       mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
-       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
 /*
index f684cfedcca9836e5bdec9877adef28984b34f03..9f4f2999fdd076e5c13aceaa9e5f3734c6ec65ba 100644 (file)
@@ -190,6 +190,7 @@ ENTRY(arm946_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index ba3c500584ac4808b58926c9c0ec9bf945483795..23a8e4c7f2bdc5c8a2431e3aba75eea54e08a6b7 100644 (file)
@@ -232,6 +232,7 @@ ENTRY(feroceon_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*
index cdfedc5b8ad83f26fb4e89d77aa4d234e473717f..b0475468c711f6a5a584758b260cb8e526ef1e6a 100644 (file)
@@ -193,6 +193,7 @@ ENTRY(mohawk_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     r0, #0
        mov     pc, lr
 
 /*