sh: switch to generic strncpy_from_user().
This kills off the special sh32/64 versions and adopts the generic version. It should be possible to optimize this for SH-4A unaligned loads, but this is a corner case that can be supported incrementally. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Родитель
94fa83c424
Коммит
0e100e11bd
|
@ -32,6 +32,7 @@ config SUPERH
|
|||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
help
|
||||
The SuperH is a RISC processor targeted for use in embedded systems
|
||||
and consumer electronics; it was also used in the Sega Dreamcast
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
(__chk_user_ptr(addr), \
|
||||
__access_ok((unsigned long __force)(addr), (size)))
|
||||
|
||||
#define user_addr_max() (current_thread_info()->addr_limit.seg)
|
||||
|
||||
/*
|
||||
* Uh, these should become the main single-value transfer routines ...
|
||||
* They automatically use the right size if we just have the right
|
||||
|
@ -100,6 +102,8 @@ struct __large_struct { unsigned long buf[100]; };
|
|||
# include "uaccess_64.h"
|
||||
#endif
|
||||
|
||||
extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
||||
|
||||
/* Generic arbitrary sized copy. */
|
||||
/* Return the number of bytes NOT copied */
|
||||
__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
|
||||
|
@ -137,37 +141,6 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
|
|||
__cl_size; \
|
||||
})
|
||||
|
||||
/**
|
||||
* strncpy_from_user: - Copy a NUL terminated string from userspace.
|
||||
* @dst: Destination address, in kernel space. This buffer must be at
|
||||
* least @count bytes long.
|
||||
* @src: Source address, in user space.
|
||||
* @count: Maximum number of bytes to copy, including the trailing NUL.
|
||||
*
|
||||
* Copies a NUL-terminated string from userspace to kernel space.
|
||||
*
|
||||
* On success, returns the length of the string (not including the trailing
|
||||
* NUL).
|
||||
*
|
||||
* If access to userspace fails, returns -EFAULT (some data may have been
|
||||
* copied).
|
||||
*
|
||||
* If @count is smaller than the length of the string, copies @count bytes
|
||||
* and returns @count.
|
||||
*/
|
||||
#define strncpy_from_user(dest,src,count) \
|
||||
({ \
|
||||
unsigned long __sfu_src = (unsigned long)(src); \
|
||||
int __sfu_count = (int)(count); \
|
||||
long __sfu_res = -EFAULT; \
|
||||
\
|
||||
if (__access_ok(__sfu_src, __sfu_count)) \
|
||||
__sfu_res = __strncpy_from_user((unsigned long)(dest), \
|
||||
__sfu_src, __sfu_count); \
|
||||
\
|
||||
__sfu_res; \
|
||||
})
|
||||
|
||||
static inline unsigned long
|
||||
copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
|
|
|
@ -170,45 +170,6 @@ __asm__ __volatile__( \
|
|||
|
||||
extern void __put_user_unknown(void);
|
||||
|
||||
static inline int
|
||||
__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count)
|
||||
{
|
||||
__kernel_size_t res;
|
||||
unsigned long __dummy, _d, _s, _c;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"9:\n"
|
||||
"mov.b @%2+, %1\n\t"
|
||||
"cmp/eq #0, %1\n\t"
|
||||
"bt/s 2f\n"
|
||||
"1:\n"
|
||||
"mov.b %1, @%3\n\t"
|
||||
"dt %4\n\t"
|
||||
"bf/s 9b\n\t"
|
||||
" add #1, %3\n\t"
|
||||
"2:\n\t"
|
||||
"sub %4, %0\n"
|
||||
"3:\n"
|
||||
".section .fixup,\"ax\"\n"
|
||||
"4:\n\t"
|
||||
"mov.l 5f, %1\n\t"
|
||||
"jmp @%1\n\t"
|
||||
" mov %9, %0\n\t"
|
||||
".balign 4\n"
|
||||
"5: .long 3b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
" .balign 4\n"
|
||||
" .long 9b,4b\n"
|
||||
".previous"
|
||||
: "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c)
|
||||
: "0" (__count), "2" (__src), "3" (__dest), "4" (__count),
|
||||
"i" (-EFAULT)
|
||||
: "memory", "t");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the size of a string (including the ending 0 even when we have
|
||||
* exceeded the maximum string length).
|
||||
|
|
|
@ -85,7 +85,5 @@ extern long __put_user_asm_q(void *, long);
|
|||
extern void __put_user_unknown(void);
|
||||
|
||||
extern long __strnlen_user(const char *__s, long __n);
|
||||
extern int __strncpy_from_user(unsigned long __dest,
|
||||
unsigned long __user __src, int __count);
|
||||
|
||||
#endif /* __ASM_SH_UACCESS_64_H */
|
||||
|
|
|
@ -1568,46 +1568,6 @@ ___clear_user_exit:
|
|||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
/*
|
||||
* int __strncpy_from_user(unsigned long __dest, unsigned long __src,
|
||||
* int __count)
|
||||
*
|
||||
* Inputs:
|
||||
* (r2) target address
|
||||
* (r3) source address
|
||||
* (r4) maximum size in bytes
|
||||
*
|
||||
* Ouputs:
|
||||
* (*r2) copied data
|
||||
* (r2) -EFAULT (in case of faulting)
|
||||
* copied data (otherwise)
|
||||
*/
|
||||
.global __strncpy_from_user
|
||||
__strncpy_from_user:
|
||||
pta ___strncpy_from_user1, tr0
|
||||
pta ___strncpy_from_user_done, tr1
|
||||
or r4, ZERO, r5 /* r5 = original count */
|
||||
beq/u r4, r63, tr1 /* early exit if r4==0 */
|
||||
movi -(EFAULT), r6 /* r6 = reply, no real fixup */
|
||||
or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
|
||||
|
||||
___strncpy_from_user1:
|
||||
ld.b r3, 0, r7 /* Fault address: only in reading */
|
||||
st.b r2, 0, r7
|
||||
addi r2, 1, r2
|
||||
addi r3, 1, r3
|
||||
beq/u ZERO, r7, tr1
|
||||
addi r4, -1, r4 /* return real number of copied bytes */
|
||||
bne/l ZERO, r4, tr0
|
||||
|
||||
___strncpy_from_user_done:
|
||||
sub r5, r4, r6 /* If done, return copied */
|
||||
|
||||
___strncpy_from_user_exit:
|
||||
or r6, ZERO, r2
|
||||
ptabs LINK, tr0
|
||||
blink tr0, ZERO
|
||||
|
||||
/*
|
||||
* extern long __strnlen_user(const char *__s, long __n)
|
||||
*
|
||||
|
@ -1982,7 +1942,6 @@ asm_uaccess_start:
|
|||
.long ___copy_user2, ___copy_user_exit
|
||||
.long ___clear_user1, ___clear_user_exit
|
||||
#endif
|
||||
.long ___strncpy_from_user1, ___strncpy_from_user_exit
|
||||
.long ___strnlen_user1, ___strnlen_user_exit
|
||||
.long ___get_user_asm_b1, ___get_user_asm_b_exit
|
||||
.long ___get_user_asm_w1, ___get_user_asm_w_exit
|
||||
|
|
|
@ -33,7 +33,6 @@ EXPORT_SYMBOL(__get_user_asm_w);
|
|||
EXPORT_SYMBOL(__get_user_asm_l);
|
||||
EXPORT_SYMBOL(__get_user_asm_q);
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
EXPORT_SYMBOL(__clear_user);
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
EXPORT_SYMBOL(__copy_user);
|
||||
|
|
Загрузка…
Ссылка в новой задаче