diff mbox series

[v3,4/9] arc: use generic strncpy/strnlen from_user

Message ID 20210722124814.778059-5-arnd@kernel.org
State Not Applicable
Headers show
Series asm-generic: strncpy_from_user/strnlen_user cleanup | expand

Commit Message

Arnd Bergmann July 22, 2021, 12:48 p.m. UTC
From: Arnd Bergmann <arnd@arndb.de>

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.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arc/Kconfig               |  2 +
 arch/arc/include/asm/uaccess.h | 83 ++--------------------------------
 arch/arc/mm/extable.c          | 12 -----
 3 files changed, 7 insertions(+), 90 deletions(-)

Comments

Christoph Hellwig July 22, 2021, 1 p.m. UTC | #1
On Thu, Jul 22, 2021 at 02:48:09PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> 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.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>
Vineet Gupta July 22, 2021, 3:34 p.m. UTC | #2
On 7/22/21 5:48 AM, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> 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.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

LGTM. Thx for doing this Arnd !

Acked-by: Vineet Gupta <vgupta@synopsys.com>

-Vineet

> ---
>   arch/arc/Kconfig               |  2 +
>   arch/arc/include/asm/uaccess.h | 83 ++--------------------------------
>   arch/arc/mm/extable.c          | 12 -----
>   3 files changed, 7 insertions(+), 90 deletions(-)
>
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index d8f51eb8963b..64e5f9366401 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -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
> diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
> index 3476348f361e..754a23f26736 100644
> --- a/arch/arc/include/asm/uaccess.h
> +++ b/arch/arc/include/asm/uaccess.h
> @@ -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>
>   
> diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c
> index b06b09ddf924..4e14c4244ea2 100644
> --- a/arch/arc/mm/extable.c
> +++ b/arch/arc/mm/extable.c
> @@ -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
diff mbox series

Patch

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index d8f51eb8963b..64e5f9366401 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -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
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index 3476348f361e..754a23f26736 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -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>
 
diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c
index b06b09ddf924..4e14c4244ea2 100644
--- a/arch/arc/mm/extable.c
+++ b/arch/arc/mm/extable.c
@@ -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