mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 09:14:19 +08:00
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:
parent
2820cfdc08
commit
c52801a774
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user