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: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2020-01-16 15:58:41 +01:00
parent 2820cfdc08
commit c52801a774
3 changed files with 7 additions and 90 deletions

View File

@ -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

View File

@ -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>

View File

@ -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