Commit 0e100e11 authored by Paul Mundt's avatar Paul Mundt

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: default avatarPaul Mundt <lethal@linux-sh.org>
parent 94fa83c4
...@@ -32,6 +32,7 @@ config SUPERH ...@@ -32,6 +32,7 @@ config SUPERH
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
select GENERIC_STRNCPY_FROM_USER
help help
The SuperH is a RISC processor targeted for use in embedded systems The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast and consumer electronics; it was also used in the Sega Dreamcast
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
(__chk_user_ptr(addr), \ (__chk_user_ptr(addr), \
__access_ok((unsigned long __force)(addr), (size))) __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 ... * Uh, these should become the main single-value transfer routines ...
* They automatically use the right size if we just have the right * They automatically use the right size if we just have the right
...@@ -100,6 +102,8 @@ struct __large_struct { unsigned long buf[100]; }; ...@@ -100,6 +102,8 @@ struct __large_struct { unsigned long buf[100]; };
# include "uaccess_64.h" # include "uaccess_64.h"
#endif #endif
extern long strncpy_from_user(char *dest, const char __user *src, long count);
/* Generic arbitrary sized copy. */ /* Generic arbitrary sized copy. */
/* Return the number of bytes NOT copied */ /* Return the number of bytes NOT copied */
__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); __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); ...@@ -137,37 +141,6 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
__cl_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 static inline unsigned long
copy_from_user(void *to, const void __user *from, unsigned long n) copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
......
...@@ -170,45 +170,6 @@ __asm__ __volatile__( \ ...@@ -170,45 +170,6 @@ __asm__ __volatile__( \
extern void __put_user_unknown(void); 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 * Return the size of a string (including the ending 0 even when we have
* exceeded the maximum string length). * exceeded the maximum string length).
......
...@@ -85,7 +85,5 @@ extern long __put_user_asm_q(void *, long); ...@@ -85,7 +85,5 @@ extern long __put_user_asm_q(void *, long);
extern void __put_user_unknown(void); extern void __put_user_unknown(void);
extern long __strnlen_user(const char *__s, long __n); 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 */ #endif /* __ASM_SH_UACCESS_64_H */
...@@ -1568,46 +1568,6 @@ ___clear_user_exit: ...@@ -1568,46 +1568,6 @@ ___clear_user_exit:
#endif /* CONFIG_MMU */ #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) * extern long __strnlen_user(const char *__s, long __n)
* *
...@@ -1982,7 +1942,6 @@ asm_uaccess_start: ...@@ -1982,7 +1942,6 @@ asm_uaccess_start:
.long ___copy_user2, ___copy_user_exit .long ___copy_user2, ___copy_user_exit
.long ___clear_user1, ___clear_user_exit .long ___clear_user1, ___clear_user_exit
#endif #endif
.long ___strncpy_from_user1, ___strncpy_from_user_exit
.long ___strnlen_user1, ___strnlen_user_exit .long ___strnlen_user1, ___strnlen_user_exit
.long ___get_user_asm_b1, ___get_user_asm_b_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit
.long ___get_user_asm_w1, ___get_user_asm_w_exit .long ___get_user_asm_w1, ___get_user_asm_w_exit
......
...@@ -33,7 +33,6 @@ EXPORT_SYMBOL(__get_user_asm_w); ...@@ -33,7 +33,6 @@ EXPORT_SYMBOL(__get_user_asm_w);
EXPORT_SYMBOL(__get_user_asm_l); EXPORT_SYMBOL(__get_user_asm_l);
EXPORT_SYMBOL(__get_user_asm_q); EXPORT_SYMBOL(__get_user_asm_q);
EXPORT_SYMBOL(__strnlen_user); EXPORT_SYMBOL(__strnlen_user);
EXPORT_SYMBOL(__strncpy_from_user);
EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(__clear_user);
EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__copy_user);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment