aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-04-27 08:08:53 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-05-02 06:12:49 -0400
commitc5102f5935503ebebad46e137d0eef68f272cc16 (patch)
tree888332340ca07cbd2a648fa603b8b252af02252a /arch
parent435a7ef52db7d86e67a009b36cac1457f8972391 (diff)
ARM: 7408/1: cacheflush: return error to userspace when flushing syscall fails
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/cacheflush.h4
-rw-r--r--arch/arm/kernel/traps.c11
-rw-r--r--arch/arm/mm/cache-v3.S1
-rw-r--r--arch/arm/mm/cache-v4.S1
-rw-r--r--arch/arm/mm/cache-v4wb.S6
-rw-r--r--arch/arm/mm/cache-v4wt.S1
-rw-r--r--arch/arm/mm/cache-v6.S10
-rw-r--r--arch/arm/mm/cache-v7.S10
-rw-r--r--arch/arm/mm/proc-arm1020.S1
-rw-r--r--arch/arm/mm/proc-arm1020e.S1
-rw-r--r--arch/arm/mm/proc-arm1022.S1
-rw-r--r--arch/arm/mm/proc-arm1026.S1
-rw-r--r--arch/arm/mm/proc-arm920.S1
-rw-r--r--arch/arm/mm/proc-arm922.S1
-rw-r--r--arch/arm/mm/proc-arm925.S1
-rw-r--r--arch/arm/mm/proc-arm926.S1
-rw-r--r--arch/arm/mm/proc-arm940.S6
-rw-r--r--arch/arm/mm/proc-arm946.S1
-rw-r--r--arch/arm/mm/proc-feroceon.S1
-rw-r--r--arch/arm/mm/proc-mohawk.S1
20 files changed, 35 insertions, 26 deletions
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 1252a2675ca..004c1bc95d2 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -101,7 +101,7 @@ struct cpu_cache_fns {
101 void (*flush_user_range)(unsigned long, unsigned long, unsigned int); 101 void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
102 102
103 void (*coherent_kern_range)(unsigned long, unsigned long); 103 void (*coherent_kern_range)(unsigned long, unsigned long);
104 void (*coherent_user_range)(unsigned long, unsigned long); 104 int (*coherent_user_range)(unsigned long, unsigned long);
105 void (*flush_kern_dcache_area)(void *, size_t); 105 void (*flush_kern_dcache_area)(void *, size_t);
106 106
107 void (*dma_map_area)(const void *, size_t, int); 107 void (*dma_map_area)(const void *, size_t, int);
@@ -142,7 +142,7 @@ extern void __cpuc_flush_kern_all(void);
142extern void __cpuc_flush_user_all(void); 142extern void __cpuc_flush_user_all(void);
143extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); 143extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
144extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); 144extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
145extern void __cpuc_coherent_user_range(unsigned long, unsigned long); 145extern int __cpuc_coherent_user_range(unsigned long, unsigned long);
146extern void __cpuc_flush_dcache_area(void *, size_t); 146extern void __cpuc_flush_dcache_area(void *, size_t);
147 147
148/* 148/*
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 63d402f75e2..3647170e9a1 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -479,14 +479,14 @@ static int bad_syscall(int n, struct pt_regs *regs)
479 return regs->ARM_r0; 479 return regs->ARM_r0;
480} 480}
481 481
482static inline void 482static inline int
483do_cache_op(unsigned long start, unsigned long end, int flags) 483do_cache_op(unsigned long start, unsigned long end, int flags)
484{ 484{
485 struct mm_struct *mm = current->active_mm; 485 struct mm_struct *mm = current->active_mm;
486 struct vm_area_struct *vma; 486 struct vm_area_struct *vma;
487 487
488 if (end < start || flags) 488 if (end < start || flags)
489 return; 489 return -EINVAL;
490 490
491 down_read(&mm->mmap_sem); 491 down_read(&mm->mmap_sem);
492 vma = find_vma(mm, start); 492 vma = find_vma(mm, start);
@@ -497,10 +497,10 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
497 end = vma->vm_end; 497 end = vma->vm_end;
498 498
499 up_read(&mm->mmap_sem); 499 up_read(&mm->mmap_sem);
500 flush_cache_user_range(start, end); 500 return flush_cache_user_range(start, end);
501 return;
502 } 501 }
503 up_read(&mm->mmap_sem); 502 up_read(&mm->mmap_sem);
503 return -EINVAL;
504} 504}
505 505
506/* 506/*
@@ -546,8 +546,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
546 * the specified region). 546 * the specified region).
547 */ 547 */
548 case NR(cacheflush): 548 case NR(cacheflush):
549 do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2); 549 return do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
550 return 0;
551 550
552 case NR(usr26): 551 case NR(usr26):
553 if (!(elf_hwcap & HWCAP_26BIT)) 552 if (!(elf_hwcap & HWCAP_26BIT))
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index c2301f22610..52e35f32eef 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -78,6 +78,7 @@ ENTRY(v3_coherent_kern_range)
78 * - end - virtual end address 78 * - end - virtual end address
79 */ 79 */
80ENTRY(v3_coherent_user_range) 80ENTRY(v3_coherent_user_range)
81 mov r0, #0
81 mov pc, lr 82 mov pc, lr
82 83
83/* 84/*
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index fd9bb7addc8..022135d2b7e 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -88,6 +88,7 @@ ENTRY(v4_coherent_kern_range)
88 * - end - virtual end address 88 * - end - virtual end address
89 */ 89 */
90ENTRY(v4_coherent_user_range) 90ENTRY(v4_coherent_user_range)
91 mov r0, #0
91 mov pc, lr 92 mov pc, lr
92 93
93/* 94/*
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 4f2c14151cc..8f1eeae340c 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -167,9 +167,9 @@ ENTRY(v4wb_coherent_user_range)
167 add r0, r0, #CACHE_DLINESIZE 167 add r0, r0, #CACHE_DLINESIZE
168 cmp r0, r1 168 cmp r0, r1
169 blo 1b 169 blo 1b
170 mov ip, #0 170 mov r0, #0
171 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache 171 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
172 mcr p15, 0, ip, c7, c10, 4 @ drain WB 172 mcr p15, 0, r0, c7, c10, 4 @ drain WB
173 mov pc, lr 173 mov pc, lr
174 174
175 175
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index 4d7b467631c..b34a5f908a8 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -125,6 +125,7 @@ ENTRY(v4wt_coherent_user_range)
125 add r0, r0, #CACHE_DLINESIZE 125 add r0, r0, #CACHE_DLINESIZE
126 cmp r0, r1 126 cmp r0, r1
127 blo 1b 127 blo 1b
128 mov r0, #0
128 mov pc, lr 129 mov pc, lr
129 130
130/* 131/*
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 74c2e5a33a4..4b10760c56d 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -12,6 +12,7 @@
12#include <linux/linkage.h> 12#include <linux/linkage.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <asm/assembler.h> 14#include <asm/assembler.h>
15#include <asm/errno.h>
15#include <asm/unwind.h> 16#include <asm/unwind.h>
16 17
17#include "proc-macros.S" 18#include "proc-macros.S"
@@ -135,7 +136,6 @@ ENTRY(v6_coherent_user_range)
1351: 1361:
136 USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line 137 USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line
137 add r0, r0, #CACHE_LINE_SIZE 138 add r0, r0, #CACHE_LINE_SIZE
1382:
139 cmp r0, r1 139 cmp r0, r1
140 blo 1b 140 blo 1b
141#endif 141#endif
@@ -154,13 +154,11 @@ ENTRY(v6_coherent_user_range)
154 154
155/* 155/*
156 * Fault handling for the cache operation above. If the virtual address in r0 156 * Fault handling for the cache operation above. If the virtual address in r0
157 * isn't mapped, just try the next page. 157 * isn't mapped, fail with -EFAULT.
158 */ 158 */
1599001: 1599001:
160 mov r0, r0, lsr #12 160 mov r0, #-EFAULT
161 mov r0, r0, lsl #12 161 mov pc, lr
162 add r0, r0, #4096
163 b 2b
164 UNWIND(.fnend ) 162 UNWIND(.fnend )
165ENDPROC(v6_coherent_user_range) 163ENDPROC(v6_coherent_user_range)
166ENDPROC(v6_coherent_kern_range) 164ENDPROC(v6_coherent_kern_range)
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index a655d3da386..39e3fb3db80 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -13,6 +13,7 @@
13#include <linux/linkage.h> 13#include <linux/linkage.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <asm/assembler.h> 15#include <asm/assembler.h>
16#include <asm/errno.h>
16#include <asm/unwind.h> 17#include <asm/unwind.h>
17 18
18#include "proc-macros.S" 19#include "proc-macros.S"
@@ -198,7 +199,6 @@ ENTRY(v7_coherent_user_range)
198 add r12, r12, r2 199 add r12, r12, r2
199 cmp r12, r1 200 cmp r12, r1
200 blo 2b 201 blo 2b
2013:
202 mov r0, #0 202 mov r0, #0
203 ALT_SMP(mcr p15, 0, r0, c7, c1, 6) @ invalidate BTB Inner Shareable 203 ALT_SMP(mcr p15, 0, r0, c7, c1, 6) @ invalidate BTB Inner Shareable
204 ALT_UP(mcr p15, 0, r0, c7, c5, 6) @ invalidate BTB 204 ALT_UP(mcr p15, 0, r0, c7, c5, 6) @ invalidate BTB
@@ -208,13 +208,11 @@ ENTRY(v7_coherent_user_range)
208 208
209/* 209/*
210 * Fault handling for the cache operation above. If the virtual address in r0 210 * Fault handling for the cache operation above. If the virtual address in r0
211 * isn't mapped, just try the next page. 211 * isn't mapped, fail with -EFAULT.
212 */ 212 */
2139001: 2139001:
214 mov r12, r12, lsr #12 214 mov r0, #-EFAULT
215 mov r12, r12, lsl #12 215 mov pc, lr
216 add r12, r12, #4096
217 b 3b
218 UNWIND(.fnend ) 216 UNWIND(.fnend )
219ENDPROC(v7_coherent_kern_range) 217ENDPROC(v7_coherent_kern_range)
220ENDPROC(v7_coherent_user_range) 218ENDPROC(v7_coherent_user_range)
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 234951345eb..0650bb87c1e 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -241,6 +241,7 @@ ENTRY(arm1020_coherent_user_range)
241 cmp r0, r1 241 cmp r0, r1
242 blo 1b 242 blo 1b
243 mcr p15, 0, ip, c7, c10, 4 @ drain WB 243 mcr p15, 0, ip, c7, c10, 4 @ drain WB
244 mov r0, #0
244 mov pc, lr 245 mov pc, lr
245 246
246/* 247/*
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index c244b06caac..4188478325a 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -235,6 +235,7 @@ ENTRY(arm1020e_coherent_user_range)
235 cmp r0, r1 235 cmp r0, r1
236 blo 1b 236 blo 1b
237 mcr p15, 0, ip, c7, c10, 4 @ drain WB 237 mcr p15, 0, ip, c7, c10, 4 @ drain WB
238 mov r0, #0
238 mov pc, lr 239 mov pc, lr
239 240
240/* 241/*
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 38fe22efd18..33c68824bff 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -224,6 +224,7 @@ ENTRY(arm1022_coherent_user_range)
224 cmp r0, r1 224 cmp r0, r1
225 blo 1b 225 blo 1b
226 mcr p15, 0, ip, c7, c10, 4 @ drain WB 226 mcr p15, 0, ip, c7, c10, 4 @ drain WB
227 mov r0, #0
227 mov pc, lr 228 mov pc, lr
228 229
229/* 230/*
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 3eb9c3c26c7..fbc1d5fc24d 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -218,6 +218,7 @@ ENTRY(arm1026_coherent_user_range)
218 cmp r0, r1 218 cmp r0, r1
219 blo 1b 219 blo 1b
220 mcr p15, 0, ip, c7, c10, 4 @ drain WB 220 mcr p15, 0, ip, c7, c10, 4 @ drain WB
221 mov r0, #0
221 mov pc, lr 222 mov pc, lr
222 223
223/* 224/*
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index cb941ae95f6..1a8c138eb89 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -210,6 +210,7 @@ ENTRY(arm920_coherent_user_range)
210 cmp r0, r1 210 cmp r0, r1
211 blo 1b 211 blo 1b
212 mcr p15, 0, r0, c7, c10, 4 @ drain WB 212 mcr p15, 0, r0, c7, c10, 4 @ drain WB
213 mov r0, #0
213 mov pc, lr 214 mov pc, lr
214 215
215/* 216/*
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 4ec0e074dd5..4c44d7e1c3c 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -212,6 +212,7 @@ ENTRY(arm922_coherent_user_range)
212 cmp r0, r1 212 cmp r0, r1
213 blo 1b 213 blo 1b
214 mcr p15, 0, r0, c7, c10, 4 @ drain WB 214 mcr p15, 0, r0, c7, c10, 4 @ drain WB
215 mov r0, #0
215 mov pc, lr 216 mov pc, lr
216 217
217/* 218/*
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 9dccd9a365b..ec5b1180994 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -258,6 +258,7 @@ ENTRY(arm925_coherent_user_range)
258 cmp r0, r1 258 cmp r0, r1
259 blo 1b 259 blo 1b
260 mcr p15, 0, r0, c7, c10, 4 @ drain WB 260 mcr p15, 0, r0, c7, c10, 4 @ drain WB
261 mov r0, #0
261 mov pc, lr 262 mov pc, lr
262 263
263/* 264/*
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 820259b81a1..c31e62c606c 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -221,6 +221,7 @@ ENTRY(arm926_coherent_user_range)
221 cmp r0, r1 221 cmp r0, r1
222 blo 1b 222 blo 1b
223 mcr p15, 0, r0, c7, c10, 4 @ drain WB 223 mcr p15, 0, r0, c7, c10, 4 @ drain WB
224 mov r0, #0
224 mov pc, lr 225 mov pc, lr
225 226
226/* 227/*
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 9fdc0a17097..a613a7dd714 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -160,7 +160,7 @@ ENTRY(arm940_coherent_user_range)
160 * - size - region size 160 * - size - region size
161 */ 161 */
162ENTRY(arm940_flush_kern_dcache_area) 162ENTRY(arm940_flush_kern_dcache_area)
163 mov ip, #0 163 mov r0, #0
164 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments 164 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
1651: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries 1651: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
1662: mcr p15, 0, r3, c7, c14, 2 @ clean/flush D index 1662: mcr p15, 0, r3, c7, c14, 2 @ clean/flush D index
@@ -168,8 +168,8 @@ ENTRY(arm940_flush_kern_dcache_area)
168 bcs 2b @ entries 63 to 0 168 bcs 2b @ entries 63 to 0
169 subs r1, r1, #1 << 4 169 subs r1, r1, #1 << 4
170 bcs 1b @ segments 7 to 0 170 bcs 1b @ segments 7 to 0
171 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache 171 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
172 mcr p15, 0, ip, c7, c10, 4 @ drain WB 172 mcr p15, 0, r0, c7, c10, 4 @ drain WB
173 mov pc, lr 173 mov pc, lr
174 174
175/* 175/*
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index f684cfedcca..9f4f2999fdd 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -190,6 +190,7 @@ ENTRY(arm946_coherent_user_range)
190 cmp r0, r1 190 cmp r0, r1
191 blo 1b 191 blo 1b
192 mcr p15, 0, r0, c7, c10, 4 @ drain WB 192 mcr p15, 0, r0, c7, c10, 4 @ drain WB
193 mov r0, #0
193 mov pc, lr 194 mov pc, lr
194 195
195/* 196/*
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index ba3c500584a..23a8e4c7f2b 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -232,6 +232,7 @@ ENTRY(feroceon_coherent_user_range)
232 cmp r0, r1 232 cmp r0, r1
233 blo 1b 233 blo 1b
234 mcr p15, 0, r0, c7, c10, 4 @ drain WB 234 mcr p15, 0, r0, c7, c10, 4 @ drain WB
235 mov r0, #0
235 mov pc, lr 236 mov pc, lr
236 237
237/* 238/*
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index cdfedc5b8ad..b0475468c71 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -193,6 +193,7 @@ ENTRY(mohawk_coherent_user_range)
193 cmp r0, r1 193 cmp r0, r1
194 blo 1b 194 blo 1b
195 mcr p15, 0, r0, c7, c10, 4 @ drain WB 195 mcr p15, 0, r0, c7, c10, 4 @ drain WB
196 mov r0, #0
196 mov pc, lr 197 mov pc, lr
197 198
198/* 199/*