Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2d25a53 authored by Vladimir Murzin's avatar Vladimir Murzin Committed by Will Deacon
Browse files

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: default avatarVladimir Murzin <vladimir.murzin@arm.com>
[will: changed internal return value from -EINTR to 0 to match arch/arm/]
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent a1ae65b2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ extern void flush_cache_all(void);
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
extern void flush_icache_range(unsigned long start, unsigned long end);
extern void __flush_dcache_area(void *addr, size_t len);
extern void __flush_cache_user_range(unsigned long start, unsigned long end);
extern long __flush_cache_user_range(unsigned long start, unsigned long end);

static inline void flush_cache_mm(struct mm_struct *mm)
{
+29 −20
Original line number Diff line number Diff line
@@ -28,29 +28,39 @@
#include <asm/cacheflush.h>
#include <asm/unistd.h>

static inline void
do_compat_cache_op(unsigned long start, unsigned long end, int flags)
static long
__do_compat_cache_op(unsigned long start, unsigned long end)
{
	struct mm_struct *mm = current->active_mm;
	struct vm_area_struct *vma;
	long ret;

	if (end < start || flags)
		return;
	do {
		unsigned long chunk = min(PAGE_SIZE, end - start);

	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;
		up_read(&mm->mmap_sem);
		__flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end));
		return;
	}
	up_read(&mm->mmap_sem);
		if (fatal_signal_pending(current))
			return 0;

		ret = __flush_cache_user_range(start, start + chunk);
		if (ret)
			return ret;

		cond_resched();
		start += chunk;
	} while (start < end);

	return 0;
}

static inline long
do_compat_cache_op(unsigned long start, unsigned long end, int flags)
{
	if (end < start || flags)
		return -EINVAL;

	if (!access_ok(VERIFY_READ, start, end - start))
		return -EFAULT;

	return __do_compat_cache_op(start, end);
}
/*
 * Handle all unrecognised system calls.
 */
@@ -74,8 +84,7 @@ long compat_arm_syscall(struct pt_regs *regs)
	 * the specified region).
	 */
	case __ARM_NR_compat_cacheflush:
		do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
		return 0;
		return do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);

	case __ARM_NR_compat_set_tls:
		current->thread.tp_value = regs->regs[0];
+5 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
@@ -140,9 +141,12 @@ USER(9f, ic ivau, x4 ) // invalidate I line PoU
	add	x4, x4, x2
	cmp	x4, x1
	b.lo	1b
9:						// ignore any faulting cache operation
	dsb	ish
	isb
	mov	x0, #0
	ret
9:
	mov	x0, #-EFAULT
	ret
ENDPROC(flush_icache_range)
ENDPROC(__flush_cache_user_range)