Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+4 −31
Original line number Diff line number Diff line
@@ -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)
{
+0 −39
Original line number Diff line number Diff line
@@ -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).
+0 −2
Original line number Diff line number Diff line
@@ -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 */
+0 −41
Original line number Diff line number Diff line
@@ -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
Loading