|
@@ -499,6 +499,54 @@ static int bad_syscall(int n, struct pt_regs *regs)
|
|
|
return regs->ARM_r0;
|
|
|
}
|
|
|
|
|
|
+static long do_cache_op_restart(struct restart_block *);
|
|
|
+
|
|
|
+static inline int
|
|
|
+__do_cache_op(unsigned long start, unsigned long end)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ unsigned long chunk = PAGE_SIZE;
|
|
|
+
|
|
|
+ do {
|
|
|
+ if (signal_pending(current)) {
|
|
|
+ struct thread_info *ti = current_thread_info();
|
|
|
+
|
|
|
+ ti->restart_block = (struct restart_block) {
|
|
|
+ .fn = do_cache_op_restart,
|
|
|
+ };
|
|
|
+
|
|
|
+ ti->arm_restart_block = (struct arm_restart_block) {
|
|
|
+ {
|
|
|
+ .cache = {
|
|
|
+ .start = start,
|
|
|
+ .end = end,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ return -ERESTART_RESTARTBLOCK;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = flush_cache_user_range(start, start + chunk);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ cond_resched();
|
|
|
+ start += chunk;
|
|
|
+ } while (start < end);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static long do_cache_op_restart(struct restart_block *unused)
|
|
|
+{
|
|
|
+ struct arm_restart_block *restart_block;
|
|
|
+
|
|
|
+ restart_block = ¤t_thread_info()->arm_restart_block;
|
|
|
+ return __do_cache_op(restart_block->cache.start,
|
|
|
+ restart_block->cache.end);
|
|
|
+}
|
|
|
+
|
|
|
static inline int
|
|
|
do_cache_op(unsigned long start, unsigned long end, int flags)
|
|
|
{
|
|
@@ -510,17 +558,18 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
|
|
|
|
|
|
down_read(&mm->mmap_sem);
|
|
|
vma = find_vma(mm, start);
|
|
|
- if (vma && vma->vm_start < end) {
|
|
|
- if (start < vma->vm_start)
|
|
|
- start = vma->vm_start;
|
|
|
- if (end > vma->vm_end)
|
|
|
- end = vma->vm_end;
|
|
|
-
|
|
|
+ if (!vma || vma->vm_start >= end) {
|
|
|
up_read(&mm->mmap_sem);
|
|
|
- return flush_cache_user_range(start, end);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
+
|
|
|
+ if (start < vma->vm_start)
|
|
|
+ start = vma->vm_start;
|
|
|
+ if (end > vma->vm_end)
|
|
|
+ end = vma->vm_end;
|
|
|
up_read(&mm->mmap_sem);
|
|
|
- return -EINVAL;
|
|
|
+
|
|
|
+ return __do_cache_op(start, end);
|
|
|
}
|
|
|
|
|
|
/*
|