aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
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/arm/kernel
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/arm/kernel')
-rw-r--r--arch/arm/kernel/traps.c11
1 files changed, 5 insertions, 6 deletions
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))