diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-08-28 13:38:40 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-08-28 13:38:40 -0400 |
commit | 5cc91e0460889c8461620904968e193dddb1beb3 (patch) | |
tree | 777ac3514feb2631ad650466be464041477eb706 /arch/arm/kernel | |
parent | cdf0bfb0126bbd8c5424ca01fd59fd70d8ea80f9 (diff) | |
parent | 97c72d89ce0ec8c73f19d5e35ec1f90f7a14bed7 (diff) |
Merge branch 'for-rmk/cacheflush-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into devel-stable
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/entry-common.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 66 |
2 files changed, 53 insertions, 17 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 94104bf69719..74ad15d1a065 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -442,10 +442,10 @@ local_restart: | |||
442 | ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine | 442 | ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine |
443 | 443 | ||
444 | add r1, sp, #S_OFF | 444 | add r1, sp, #S_OFF |
445 | 2: mov why, #0 @ no longer a real syscall | ||
446 | cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) | 445 | cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) |
447 | eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back | 446 | eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back |
448 | bcs arm_syscall | 447 | bcs arm_syscall |
448 | 2: mov why, #0 @ no longer a real syscall | ||
449 | b sys_ni_syscall @ not private func | 449 | b sys_ni_syscall @ not private func |
450 | 450 | ||
451 | #if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI) | 451 | #if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI) |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index ab517fcce21b..8fcda140358d 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -497,28 +497,64 @@ static int bad_syscall(int n, struct pt_regs *regs) | |||
497 | return regs->ARM_r0; | 497 | return regs->ARM_r0; |
498 | } | 498 | } |
499 | 499 | ||
500 | static long do_cache_op_restart(struct restart_block *); | ||
501 | |||
500 | static inline int | 502 | static inline int |
501 | do_cache_op(unsigned long start, unsigned long end, int flags) | 503 | __do_cache_op(unsigned long start, unsigned long end) |
502 | { | 504 | { |
503 | struct mm_struct *mm = current->active_mm; | 505 | int ret; |
504 | struct vm_area_struct *vma; | 506 | unsigned long chunk = PAGE_SIZE; |
507 | |||
508 | do { | ||
509 | if (signal_pending(current)) { | ||
510 | struct thread_info *ti = current_thread_info(); | ||
511 | |||
512 | ti->restart_block = (struct restart_block) { | ||
513 | .fn = do_cache_op_restart, | ||
514 | }; | ||
515 | |||
516 | ti->arm_restart_block = (struct arm_restart_block) { | ||
517 | { | ||
518 | .cache = { | ||
519 | .start = start, | ||
520 | .end = end, | ||
521 | }, | ||
522 | }, | ||
523 | }; | ||
524 | |||
525 | return -ERESTART_RESTARTBLOCK; | ||
526 | } | ||
527 | |||
528 | ret = flush_cache_user_range(start, start + chunk); | ||
529 | if (ret) | ||
530 | return ret; | ||
505 | 531 | ||
532 | cond_resched(); | ||
533 | start += chunk; | ||
534 | } while (start < end); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static long do_cache_op_restart(struct restart_block *unused) | ||
540 | { | ||
541 | struct arm_restart_block *restart_block; | ||
542 | |||
543 | restart_block = ¤t_thread_info()->arm_restart_block; | ||
544 | return __do_cache_op(restart_block->cache.start, | ||
545 | restart_block->cache.end); | ||
546 | } | ||
547 | |||
548 | static inline int | ||
549 | do_cache_op(unsigned long start, unsigned long end, int flags) | ||
550 | { | ||
506 | if (end < start || flags) | 551 | if (end < start || flags) |
507 | return -EINVAL; | 552 | return -EINVAL; |
508 | 553 | ||
509 | down_read(&mm->mmap_sem); | 554 | if (!access_ok(VERIFY_READ, start, end - start)) |
510 | vma = find_vma(mm, start); | 555 | return -EFAULT; |
511 | if (vma && vma->vm_start < end) { | ||
512 | if (start < vma->vm_start) | ||
513 | start = vma->vm_start; | ||
514 | if (end > vma->vm_end) | ||
515 | end = vma->vm_end; | ||
516 | 556 | ||
517 | up_read(&mm->mmap_sem); | 557 | return __do_cache_op(start, end); |
518 | return flush_cache_user_range(start, end); | ||
519 | } | ||
520 | up_read(&mm->mmap_sem); | ||
521 | return -EINVAL; | ||
522 | } | 558 | } |
523 | 559 | ||
524 | /* | 560 | /* |