2020-01-16 00:56:37

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 0/2] Switching ARC to optimized generic strncpy_from_user

Hi,

This series switches ARC to generic word-at-a-time interface.

I understand that going fwd, we may drop the inline versions altogether but this
helps ARC code in the interim.

v2 <- v1
- Moved __strnlen_user/__strncpy_from_user to under ifdef gaurd [Arnd]
- Dropped the broken optimization patch [Linus]
- Folded 2 ARC patches into 1

Thx,
-Vineet

Vineet Gupta (2):
asm-generic/uaccess: don't define inline functions if noinline lib/*
in use
ARC: uaccess: use optimized generic __strnlen_user/__strncpy_from_user

arch/arc/Kconfig | 2 +
arch/arc/include/asm/uaccess.h | 85 ++--------------------------------
arch/arc/mm/extable.c | 23 ---------
include/asm-generic/uaccess.h | 8 ++++
4 files changed, 14 insertions(+), 104 deletions(-)

--
2.20.1


2020-01-16 00:58:02

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 2/2] ARC: uaccess: use optimized generic __strnlen_user/__strncpy_from_user

The existing ARC variants have 2 issues
- Use ZOL which may not be present in forthcoming architecture
- Byte loop based vs. generic version which is word loop based

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/Kconfig | 2 +
arch/arc/include/asm/uaccess.h | 85 ++--------------------------------
arch/arc/mm/extable.c | 23 ---------
3 files changed, 6 insertions(+), 104 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 26108ea785c2..3b074c4d31fb 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -26,6 +26,8 @@ config ARC
select GENERIC_PENDING_IRQ if SMP
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
+ select GENERIC_STRNCPY_FROM_USER if MMU
+ select GENERIC_STRNLEN_USER if MMU
select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK
select HAVE_DEBUG_STACKOVERFLOW
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index ea40ec7f6cae..a3c943993b7b 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -52,6 +52,8 @@
#define __access_ok(addr, sz) (unlikely(__kernel_ok) || \
likely(__user_ok((addr), (sz))))

+#define user_addr_max() (uaccess_kernel() ? ~0UL : get_fs())
+
/*********** Single byte/hword/word copies ******************/

#define __get_user_fn(sz, u, k) \
@@ -613,7 +615,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
return res;
}

-static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
+static inline unsigned long __clear_user(void __user *to, unsigned long n)
{
long res = n;
unsigned char *d_char = to;
@@ -655,89 +657,10 @@ 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 (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;
-
- __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
+#define __clear_user __clear_user

#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..88fa3a4d4906 100644
--- a/arch/arc/mm/extable.c
+++ b/arch/arc/mm/extable.c
@@ -22,26 +22,3 @@ int fixup_exception(struct pt_regs *regs)

return 0;
}
-
-#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-
-unsigned long arc_clear_user_noinline(void __user *to,
- unsigned long n)
-{
- return __arc_clear_user(to, n);
-}
-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
--
2.20.1

2020-01-16 02:16:57

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 1/2] asm-generic/uaccess: don't define inline functions if noinline lib/* in use

There are 2 generic varaints of strncpy_from_user() / strnlen_user()
(1). inline version in asm-generic/uaccess.h
(2). optimized word-at-a-time version in lib/*

This patch disables #1 if #2 selected. This allows arches to continue
reusing asm-generic/uaccess.h for rest of code

This came up when switching ARC to generic word-at-a-time interface

Signed-off-by: Vineet Gupta <[email protected]>
---
include/asm-generic/uaccess.h | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index e935318804f8..2ea7f4e0e60e 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -212,6 +212,7 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)

extern int __get_user_bad(void) __attribute__((noreturn));

+#ifndef CONFIG_GENERIC_STRNCPY_FROM_USER
/*
* Copy a null terminated string from userspace.
*/
@@ -234,7 +235,11 @@ strncpy_from_user(char *dst, const char __user *src, long count)
return -EFAULT;
return __strncpy_from_user(dst, src, count);
}
+#else
+extern long strncpy_from_user(char *dest, const char __user *src, long count);
+#endif

+#ifndef CONFIG_GENERIC_STRNLEN_USER
/*
* Return the size of a string (including the ending 0)
*
@@ -255,6 +260,9 @@ static inline long strnlen_user(const char __user *src, long n)
return 0;
return __strnlen_user(src, n);
}
+#else
+extern __must_check long strnlen_user(const char __user *str, long n);
+#endif

/*
* Zero Userspace
--
2.20.1