aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Murzin <vladimir.murzin@arm.com>2014-12-01 05:53:08 -0500
committerWill Deacon <will.deacon@arm.com>2014-12-01 08:31:12 -0500
commita2d25a5391ca219f196f9fee7b535c40d201c6bf (patch)
tree4b2e208ebac21cf53793db6ba4ed5a74b04a6d59
parenta1ae65b219416a72c15577bd4c8c11174fffbb8b (diff)
arm64: compat: align cacheflush syscall with arch/arm
Update handling of cacheflush syscall with changes made in arch/arm counterpart: - return error to userspace when flushing syscall fails - split user cache-flushing into interruptible chunks - don't bother rounding to nearest vma Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com> [will: changed internal return value from -EINTR to 0 to match arch/arm/] Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/include/asm/cacheflush.h2
-rw-r--r--arch/arm64/kernel/sys_compat.c49
-rw-r--r--arch/arm64/mm/cache.S6
3 files changed, 35 insertions, 22 deletions
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index 689b6379188c..7ae31a2cc6c0 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -73,7 +73,7 @@ extern void flush_cache_all(void);
73extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); 73extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
74extern void flush_icache_range(unsigned long start, unsigned long end); 74extern void flush_icache_range(unsigned long start, unsigned long end);
75extern void __flush_dcache_area(void *addr, size_t len); 75extern void __flush_dcache_area(void *addr, size_t len);
76extern void __flush_cache_user_range(unsigned long start, unsigned long end); 76extern long __flush_cache_user_range(unsigned long start, unsigned long end);
77 77
78static inline void flush_cache_mm(struct mm_struct *mm) 78static inline void flush_cache_mm(struct mm_struct *mm)
79{ 79{
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index dc47e53e9e28..28c511b06edf 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -28,29 +28,39 @@
28#include <asm/cacheflush.h> 28#include <asm/cacheflush.h>
29#include <asm/unistd.h> 29#include <asm/unistd.h>
30 30
31static inline void 31static long
32do_compat_cache_op(unsigned long start, unsigned long end, int flags) 32__do_compat_cache_op(unsigned long start, unsigned long end)
33{ 33{
34 struct mm_struct *mm = current->active_mm; 34 long ret;
35 struct vm_area_struct *vma;
36 35
37 if (end < start || flags) 36 do {
38 return; 37 unsigned long chunk = min(PAGE_SIZE, end - start);
39 38
40 down_read(&mm->mmap_sem); 39 if (fatal_signal_pending(current))
41 vma = find_vma(mm, start); 40 return 0;
42 if (vma && vma->vm_start < end) { 41
43 if (start < vma->vm_start) 42 ret = __flush_cache_user_range(start, start + chunk);
44 start = vma->vm_start; 43 if (ret)
45 if (end > vma->vm_end) 44 return ret;
46 end = vma->vm_end; 45
47 up_read(&mm->mmap_sem); 46 cond_resched();
48 __flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end)); 47 start += chunk;
49 return; 48 } while (start < end);
50 } 49
51 up_read(&mm->mmap_sem); 50 return 0;
52} 51}
53 52
53static inline long
54do_compat_cache_op(unsigned long start, unsigned long end, int flags)
55{
56 if (end < start || flags)
57 return -EINVAL;
58
59 if (!access_ok(VERIFY_READ, start, end - start))
60 return -EFAULT;
61
62 return __do_compat_cache_op(start, end);
63}
54/* 64/*
55 * Handle all unrecognised system calls. 65 * Handle all unrecognised system calls.
56 */ 66 */
@@ -74,8 +84,7 @@ long compat_arm_syscall(struct pt_regs *regs)
74 * the specified region). 84 * the specified region).
75 */ 85 */
76 case __ARM_NR_compat_cacheflush: 86 case __ARM_NR_compat_cacheflush:
77 do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]); 87 return do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
78 return 0;
79 88
80 case __ARM_NR_compat_set_tls: 89 case __ARM_NR_compat_set_tls:
81 current->thread.tp_value = regs->regs[0]; 90 current->thread.tp_value = regs->regs[0];
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index 8eaf18577d71..2560e1e1562e 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -17,6 +17,7 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include <linux/errno.h>
20#include <linux/linkage.h> 21#include <linux/linkage.h>
21#include <linux/init.h> 22#include <linux/init.h>
22#include <asm/assembler.h> 23#include <asm/assembler.h>
@@ -140,9 +141,12 @@ USER(9f, ic ivau, x4 ) // invalidate I line PoU
140 add x4, x4, x2 141 add x4, x4, x2
141 cmp x4, x1 142 cmp x4, x1
142 b.lo 1b 143 b.lo 1b
1439: // ignore any faulting cache operation
144 dsb ish 144 dsb ish
145 isb 145 isb
146 mov x0, #0
147 ret
1489:
149 mov x0, #-EFAULT
146 ret 150 ret
147ENDPROC(flush_icache_range) 151ENDPROC(flush_icache_range)
148ENDPROC(__flush_cache_user_range) 152ENDPROC(__flush_cache_user_range)