--- /dev/null
+From 5bf6c07a1843813d0065feaaecba622d49148d7e Mon Sep 17 00:00:00 2001
+From: Chris Metcalf <cmetcalf@ezchip.com>
+Date: Thu, 30 Apr 2015 15:12:42 -0400
+Subject: tile: add <asm/word-at-a-time.h> and enable support functions
+
+From: Chris Metcalf <cmetcalf@ezchip.com>
+
+commit 5bf6c07a1843813d0065feaaecba622d49148d7e upstream.
+
+This change enables the generic strncpy_from_user() and strnlen_user()
+using word-at-a-time.h. The tile implementation is trivial since
+both tilepro and tilegx have SIMD operations that do byte-wise
+comparisons against immediate zero for each byte, and return an
+0x01 byte in each position where there is a 0x00 byte.
+
+Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/tile/Kconfig | 2 +
+ arch/tile/include/asm/uaccess.h | 66 +++++----------------------------
+ arch/tile/include/asm/word-at-a-time.h | 36 ++++++++++++++++++
+ arch/tile/lib/exports.c | 2 -
+ arch/tile/lib/usercopy_32.S | 46 -----------------------
+ arch/tile/lib/usercopy_64.S | 46 -----------------------
+ 6 files changed, 48 insertions(+), 150 deletions(-)
+
+--- a/arch/tile/Kconfig
++++ b/arch/tile/Kconfig
+@@ -27,6 +27,8 @@ config TILE
+ select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+ select HAVE_DEBUG_STACKOVERFLOW
+ select ARCH_WANT_FRAME_POINTERS
++ select GENERIC_STRNCPY_FROM_USER
++ select GENERIC_STRNLEN_USER
+
+ # FIXME: investigate whether we need/want these options.
+ # select HAVE_IOREMAP_PROT
+--- a/arch/tile/include/asm/uaccess.h
++++ b/arch/tile/include/asm/uaccess.h
+@@ -65,6 +65,13 @@ static inline int is_arch_mappable_range
+ #endif
+
+ /*
++ * Note that using this definition ignores is_arch_mappable_range(),
++ * so on tilepro code that uses user_addr_max() is constrained not
++ * to reference the tilepro user-interrupt region.
++ */
++#define user_addr_max() (current_thread_info()->addr_limit.seg)
++
++/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 0 if the range is valid, nonzero otherwise.
+ */
+@@ -462,62 +469,9 @@ copy_in_user(void __user *to, const void
+ #endif
+
+
+-/**
+- * strlen_user: - Get the size of a string in user space.
+- * @str: The string to measure.
+- *
+- * Context: User context only. This function may sleep.
+- *
+- * Get the size of a NUL-terminated string in user space.
+- *
+- * Returns the size of the string INCLUDING the terminating NUL.
+- * On exception, returns 0.
+- *
+- * If there is a limit on the length of a valid string, you may wish to
+- * consider using strnlen_user() instead.
+- */
+-extern long strnlen_user_asm(const char __user *str, long n);
+-static inline long __must_check strnlen_user(const char __user *str, long n)
+-{
+- might_fault();
+- return strnlen_user_asm(str, n);
+-}
+-#define strlen_user(str) strnlen_user(str, LONG_MAX)
+-
+-/**
+- * strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
+- * @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.
+- * Caller must check the specified block with access_ok() before calling
+- * this function.
+- *
+- * 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.
+- */
+-extern long strncpy_from_user_asm(char *dst, const char __user *src, long);
+-static inline long __must_check __strncpy_from_user(
+- char *dst, const char __user *src, long count)
+-{
+- might_fault();
+- return strncpy_from_user_asm(dst, src, count);
+-}
+-static inline long __must_check strncpy_from_user(
+- char *dst, const char __user *src, long count)
+-{
+- if (access_ok(VERIFY_READ, src, 1))
+- return __strncpy_from_user(dst, src, count);
+- return -EFAULT;
+-}
++extern long strnlen_user(const char __user *str, long n);
++extern long strlen_user(const char __user *str);
++extern long strncpy_from_user(char *dst, const char __user *src, long);
+
+ /**
+ * clear_user: - Zero a block of memory in user space.
+--- /dev/null
++++ b/arch/tile/include/asm/word-at-a-time.h
+@@ -0,0 +1,36 @@
++#ifndef _ASM_WORD_AT_A_TIME_H
++#define _ASM_WORD_AT_A_TIME_H
++
++#include <asm/byteorder.h>
++
++struct word_at_a_time { /* unused */ };
++#define WORD_AT_A_TIME_CONSTANTS {}
++
++/* Generate 0x01 byte values for non-zero bytes using a SIMD instruction. */
++static inline unsigned long has_zero(unsigned long val, unsigned long *data,
++ const struct word_at_a_time *c)
++{
++#ifdef __tilegx__
++ unsigned long mask = __insn_v1cmpeqi(val, 0);
++#else /* tilepro */
++ unsigned long mask = __insn_seqib(val, 0);
++#endif
++ *data = mask;
++ return mask;
++}
++
++/* These operations are both nops. */
++#define prep_zero_mask(val, data, c) (data)
++#define create_zero_mask(data) (data)
++
++/* And this operation just depends on endianness. */
++static inline long find_zero(unsigned long mask)
++{
++#ifdef __BIG_ENDIAN
++ return __builtin_clzl(mask) >> 3;
++#else
++ return __builtin_ctzl(mask) >> 3;
++#endif
++}
++
++#endif /* _ASM_WORD_AT_A_TIME_H */
+--- a/arch/tile/lib/exports.c
++++ b/arch/tile/lib/exports.c
+@@ -18,8 +18,6 @@
+
+ /* arch/tile/lib/usercopy.S */
+ #include <linux/uaccess.h>
+-EXPORT_SYMBOL(strnlen_user_asm);
+-EXPORT_SYMBOL(strncpy_from_user_asm);
+ EXPORT_SYMBOL(clear_user_asm);
+ EXPORT_SYMBOL(flush_user_asm);
+ EXPORT_SYMBOL(finv_user_asm);
+--- a/arch/tile/lib/usercopy_32.S
++++ b/arch/tile/lib/usercopy_32.S
+@@ -20,52 +20,6 @@
+ /* Access user memory, but use MMU to avoid propagating kernel exceptions. */
+
+ /*
+- * strnlen_user_asm takes the pointer in r0, and the length bound in r1.
+- * It returns the length, including the terminating NUL, or zero on exception.
+- * If length is greater than the bound, returns one plus the bound.
+- */
+-STD_ENTRY(strnlen_user_asm)
+- { bz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */
+-1: { lb_u r4, r0; addi r1, r1, -1 }
+- bz r4, 2f
+- { bnzt r1, 1b; addi r0, r0, 1 }
+-2: { sub r0, r0, r3; jrp lr }
+- STD_ENDPROC(strnlen_user_asm)
+- .pushsection .fixup,"ax"
+-strnlen_user_fault:
+- { move r0, zero; jrp lr }
+- ENDPROC(strnlen_user_fault)
+- .section __ex_table,"a"
+- .align 4
+- .word 1b, strnlen_user_fault
+- .popsection
+-
+-/*
+- * strncpy_from_user_asm takes the kernel target pointer in r0,
+- * the userspace source pointer in r1, and the length bound (including
+- * the trailing NUL) in r2. On success, it returns the string length
+- * (not including the trailing NUL), or -EFAULT on failure.
+- */
+-STD_ENTRY(strncpy_from_user_asm)
+- { bz r2, 2f; move r3, r0 }
+-1: { lb_u r4, r1; addi r1, r1, 1; addi r2, r2, -1 }
+- { sb r0, r4; addi r0, r0, 1 }
+- bz r4, 2f
+- bnzt r2, 1b
+- { sub r0, r0, r3; jrp lr }
+-2: addi r0, r0, -1 /* don't count the trailing NUL */
+- { sub r0, r0, r3; jrp lr }
+- STD_ENDPROC(strncpy_from_user_asm)
+- .pushsection .fixup,"ax"
+-strncpy_from_user_fault:
+- { movei r0, -EFAULT; jrp lr }
+- ENDPROC(strncpy_from_user_fault)
+- .section __ex_table,"a"
+- .align 4
+- .word 1b, strncpy_from_user_fault
+- .popsection
+-
+-/*
+ * clear_user_asm takes the user target address in r0 and the
+ * number of bytes to zero in r1.
+ * It returns the number of uncopiable bytes (hopefully zero) in r0.
+--- a/arch/tile/lib/usercopy_64.S
++++ b/arch/tile/lib/usercopy_64.S
+@@ -20,52 +20,6 @@
+ /* Access user memory, but use MMU to avoid propagating kernel exceptions. */
+
+ /*
+- * strnlen_user_asm takes the pointer in r0, and the length bound in r1.
+- * It returns the length, including the terminating NUL, or zero on exception.
+- * If length is greater than the bound, returns one plus the bound.
+- */
+-STD_ENTRY(strnlen_user_asm)
+- { beqz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */
+-1: { ld1u r4, r0; addi r1, r1, -1 }
+- beqz r4, 2f
+- { bnezt r1, 1b; addi r0, r0, 1 }
+-2: { sub r0, r0, r3; jrp lr }
+- STD_ENDPROC(strnlen_user_asm)
+- .pushsection .fixup,"ax"
+-strnlen_user_fault:
+- { move r0, zero; jrp lr }
+- ENDPROC(strnlen_user_fault)
+- .section __ex_table,"a"
+- .align 8
+- .quad 1b, strnlen_user_fault
+- .popsection
+-
+-/*
+- * strncpy_from_user_asm takes the kernel target pointer in r0,
+- * the userspace source pointer in r1, and the length bound (including
+- * the trailing NUL) in r2. On success, it returns the string length
+- * (not including the trailing NUL), or -EFAULT on failure.
+- */
+-STD_ENTRY(strncpy_from_user_asm)
+- { beqz r2, 2f; move r3, r0 }
+-1: { ld1u r4, r1; addi r1, r1, 1; addi r2, r2, -1 }
+- { st1 r0, r4; addi r0, r0, 1 }
+- beqz r4, 2f
+- bnezt r2, 1b
+- { sub r0, r0, r3; jrp lr }
+-2: addi r0, r0, -1 /* don't count the trailing NUL */
+- { sub r0, r0, r3; jrp lr }
+- STD_ENDPROC(strncpy_from_user_asm)
+- .pushsection .fixup,"ax"
+-strncpy_from_user_fault:
+- { movei r0, -EFAULT; jrp lr }
+- ENDPROC(strncpy_from_user_fault)
+- .section __ex_table,"a"
+- .align 8
+- .quad 1b, strncpy_from_user_fault
+- .popsection
+-
+-/*
+ * clear_user_asm takes the user target address in r0 and the
+ * number of bytes to zero in r1.
+ * It returns the number of uncopiable bytes (hopefully zero) in r0.