Commit c52801a7 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

arc: use generic strncpy/strnlen from_user



Remove the arc implemenation of strncpy/strnlen and instead use the
generic versions.  The arc version is fairly slow because it always does
byte accesses even for aligned data, and its checks for user_addr_max()
differ from the generic code.

Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 2820cfdc
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ config ARC
	select GENERIC_PENDING_IRQ if SMP
	select GENERIC_SCHED_CLOCK
	select GENERIC_SMP_IDLE_THREAD
	select GENERIC_STRNCPY_FROM_USER
	select GENERIC_STRNLEN_USER
	select HAVE_ARCH_KGDB
	select HAVE_ARCH_TRACEHOOK
	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARC_MMU_V4
+5 −78
Original line number Diff line number Diff line
@@ -655,96 +655,23 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
	return res;
}

static inline long
__arc_strncpy_from_user(char *dst, const char __user *src, long count)
{
	long res = 0;
	char val;

	if (!access_ok(src, 1))
		return -EFAULT;

	if (count == 0)
		return 0;

	__asm__ __volatile__(
	"	mov	lp_count, %5		\n"
	"	lp	3f			\n"
	"1:	ldb.ab  %3, [%2, 1]		\n"
	"	breq.d	%3, 0, 3f               \n"
	"	stb.ab  %3, [%1, 1]		\n"
	"	add	%0, %0, 1	# Num of NON NULL bytes copied	\n"
	"3:								\n"
	"	.section .fixup, \"ax\"		\n"
	"	.align 4			\n"
	"4:	mov %0, %4		# sets @res as -EFAULT	\n"
	"	j   3b				\n"
	"	.previous			\n"
	"	.section __ex_table, \"a\"	\n"
	"	.align 4			\n"
	"	.word   1b, 4b			\n"
	"	.previous			\n"
	: "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
	: "g"(-EFAULT), "r"(count)
	: "lp_count", "memory");

	return res;
}

static inline long __arc_strnlen_user(const char __user *s, long n)
{
	long res, tmp1, cnt;
	char val;

	if (!access_ok(s, 1))
		return 0;

	__asm__ __volatile__(
	"	mov %2, %1			\n"
	"1:	ldb.ab  %3, [%0, 1]		\n"
	"	breq.d  %3, 0, 2f		\n"
	"	sub.f   %2, %2, 1		\n"
	"	bnz 1b				\n"
	"	sub %2, %2, 1			\n"
	"2:	sub %0, %1, %2			\n"
	"3:	;nop				\n"
	"	.section .fixup, \"ax\"		\n"
	"	.align 4			\n"
	"4:	mov %0, 0			\n"
	"	j   3b				\n"
	"	.previous			\n"
	"	.section __ex_table, \"a\"	\n"
	"	.align 4			\n"
	"	.word 1b, 4b			\n"
	"	.previous			\n"
	: "=r"(res), "=r"(tmp1), "=r"(cnt), "=r"(val)
	: "0"(s), "1"(n)
	: "memory");

	return res;
}

#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE

#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER

#define __clear_user(d, n)		__arc_clear_user(d, n)
#define strncpy_from_user(d, s, n)	__arc_strncpy_from_user(d, s, n)
#define strnlen_user(s, n)		__arc_strnlen_user(s, n)
#else
extern unsigned long arc_clear_user_noinline(void __user *to,
		unsigned long n);
extern long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
		long count);
extern long arc_strnlen_user_noinline(const char __user *src, long n);

#define __clear_user(d, n)		arc_clear_user_noinline(d, n)
#define strncpy_from_user(d, s, n)	arc_strncpy_from_user_noinline(d, s, n)
#define strnlen_user(s, n)		arc_strnlen_user_noinline(s, n)

#endif

extern long strncpy_from_user(char *dst, const char __user *src, long count);
#define strncpy_from_user(d, s, n)	strncpy_from_user(d, s, n)
extern long strnlen_user(const char __user *src, long n);
#define strnlen_user(s, n)		strnlen_user(s, n)

#include <asm/segment.h>
#include <asm-generic/uaccess.h>

+0 −12
Original line number Diff line number Diff line
@@ -32,16 +32,4 @@ unsigned long arc_clear_user_noinline(void __user *to,
}
EXPORT_SYMBOL(arc_clear_user_noinline);

long arc_strncpy_from_user_noinline(char *dst, const char __user *src,
		long count)
{
	return __arc_strncpy_from_user(dst, src, count);
}
EXPORT_SYMBOL(arc_strncpy_from_user_noinline);

long arc_strnlen_user_noinline(const char __user *src, long n)
{
	return __arc_strnlen_user(src, n);
}
EXPORT_SYMBOL(arc_strnlen_user_noinline);
#endif