aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-06-04 02:46:05 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-06-12 21:28:37 -0400
commitcba8df4be3bdf10c86a26c458c5fc2ca978eeb2c (patch)
tree5dd9f6c93efc0588b813febe7d24178fa43d3d8b /arch/sh
parent0e100e11bd73be4e28e457cf5ad49a6892d5d1fe (diff)
sh: use the new generic strnlen_user() function
This discards both the _32 and _64 versions in favour of the consolidated generic one. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/include/asm/uaccess.h40
-rw-r--r--arch/sh/include/asm/uaccess_32.h36
-rw-r--r--arch/sh/include/asm/uaccess_64.h2
-rw-r--r--arch/sh/include/asm/word-at-a-time.h53
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S41
-rw-r--r--arch/sh/kernel/sh_ksyms_64.c1
7 files changed, 57 insertions, 117 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index cbffc26c0434..31d9db7913e4 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -33,6 +33,7 @@ config SUPERH
33 select GENERIC_CLOCKEVENTS 33 select GENERIC_CLOCKEVENTS
34 select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST 34 select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
35 select GENERIC_STRNCPY_FROM_USER 35 select GENERIC_STRNCPY_FROM_USER
36 select GENERIC_STRNLEN_USER
36 help 37 help
37 The SuperH is a RISC processor targeted for use in embedded systems 38 The SuperH is a RISC processor targeted for use in embedded systems
38 and consumer electronics; it was also used in the Sega Dreamcast 39 and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h
index 3df7eee9c155..8698a80ed00c 100644
--- a/arch/sh/include/asm/uaccess.h
+++ b/arch/sh/include/asm/uaccess.h
@@ -104,6 +104,9 @@ struct __large_struct { unsigned long buf[100]; };
104 104
105extern long strncpy_from_user(char *dest, const char __user *src, long count); 105extern long strncpy_from_user(char *dest, const char __user *src, long count);
106 106
107extern __must_check long strlen_user(const char __user *str);
108extern __must_check long strnlen_user(const char __user *str, long n);
109
107/* Generic arbitrary sized copy. */ 110/* Generic arbitrary sized copy. */
108/* Return the number of bytes NOT copied */ 111/* Return the number of bytes NOT copied */
109__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); 112__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
@@ -165,43 +168,6 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
165 return __copy_size; 168 return __copy_size;
166} 169}
167 170
168/**
169 * strnlen_user: - Get the size of a string in user space.
170 * @s: The string to measure.
171 * @n: The maximum valid length
172 *
173 * Context: User context only. This function may sleep.
174 *
175 * Get the size of a NUL-terminated string in user space.
176 *
177 * Returns the size of the string INCLUDING the terminating NUL.
178 * On exception, returns 0.
179 * If the string is too long, returns a value greater than @n.
180 */
181static inline long strnlen_user(const char __user *s, long n)
182{
183 if (!__addr_ok(s))
184 return 0;
185 else
186 return __strnlen_user(s, n);
187}
188
189/**
190 * strlen_user: - Get the size of a string in user space.
191 * @str: The string to measure.
192 *
193 * Context: User context only. This function may sleep.
194 *
195 * Get the size of a NUL-terminated string in user space.
196 *
197 * Returns the size of the string INCLUDING the terminating NUL.
198 * On exception, returns 0.
199 *
200 * If there is a limit on the length of a valid string, you may wish to
201 * consider using strnlen_user() instead.
202 */
203#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
204
205/* 171/*
206 * The exception table consists of pairs of addresses: the first is the 172 * The exception table consists of pairs of addresses: the first is the
207 * address of an instruction that is allowed to fault, and the second is 173 * address of an instruction that is allowed to fault, and the second is
diff --git a/arch/sh/include/asm/uaccess_32.h b/arch/sh/include/asm/uaccess_32.h
index ef44d05bb631..c0de7ee35ab7 100644
--- a/arch/sh/include/asm/uaccess_32.h
+++ b/arch/sh/include/asm/uaccess_32.h
@@ -170,40 +170,4 @@ __asm__ __volatile__( \
170 170
171extern void __put_user_unknown(void); 171extern void __put_user_unknown(void);
172 172
173/*
174 * Return the size of a string (including the ending 0 even when we have
175 * exceeded the maximum string length).
176 */
177static inline long __strnlen_user(const char __user *__s, long __n)
178{
179 unsigned long res;
180 unsigned long __dummy;
181
182 __asm__ __volatile__(
183 "1:\t"
184 "mov.b @(%0,%3), %1\n\t"
185 "cmp/eq %4, %0\n\t"
186 "bt/s 2f\n\t"
187 " add #1, %0\n\t"
188 "tst %1, %1\n\t"
189 "bf 1b\n\t"
190 "2:\n"
191 ".section .fixup,\"ax\"\n"
192 "3:\n\t"
193 "mov.l 4f, %1\n\t"
194 "jmp @%1\n\t"
195 " mov #0, %0\n"
196 ".balign 4\n"
197 "4: .long 2b\n"
198 ".previous\n"
199 ".section __ex_table,\"a\"\n"
200 " .balign 4\n"
201 " .long 1b,3b\n"
202 ".previous"
203 : "=z" (res), "=&r" (__dummy)
204 : "0" (0), "r" (__s), "r" (__n)
205 : "t");
206 return res;
207}
208
209#endif /* __ASM_SH_UACCESS_32_H */ 173#endif /* __ASM_SH_UACCESS_32_H */
diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h
index 0042c9054b20..2e07e0f40c6a 100644
--- a/arch/sh/include/asm/uaccess_64.h
+++ b/arch/sh/include/asm/uaccess_64.h
@@ -84,6 +84,4 @@ extern long __put_user_asm_l(void *, long);
84extern long __put_user_asm_q(void *, long); 84extern long __put_user_asm_q(void *, long);
85extern void __put_user_unknown(void); 85extern void __put_user_unknown(void);
86 86
87extern long __strnlen_user(const char *__s, long __n);
88
89#endif /* __ASM_SH_UACCESS_64_H */ 87#endif /* __ASM_SH_UACCESS_64_H */
diff --git a/arch/sh/include/asm/word-at-a-time.h b/arch/sh/include/asm/word-at-a-time.h
new file mode 100644
index 000000000000..6e38953ff7fd
--- /dev/null
+++ b/arch/sh/include/asm/word-at-a-time.h
@@ -0,0 +1,53 @@
1#ifndef __ASM_SH_WORD_AT_A_TIME_H
2#define __ASM_SH_WORD_AT_A_TIME_H
3
4#ifdef CONFIG_CPU_BIG_ENDIAN
5# include <asm-generic/word-at-a-time.h>
6#else
7/*
8 * Little-endian version cribbed from x86.
9 */
10struct word_at_a_time {
11 const unsigned long one_bits, high_bits;
12};
13
14#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
15
16/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
17static inline long count_masked_bytes(long mask)
18{
19 /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
20 long a = (0x0ff0001+mask) >> 23;
21 /* Fix the 1 for 00 case */
22 return a & mask;
23}
24
25/* Return nonzero if it has a zero */
26static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
27{
28 unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
29 *bits = mask;
30 return mask;
31}
32
33static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
34{
35 return bits;
36}
37
38static inline unsigned long create_zero_mask(unsigned long bits)
39{
40 bits = (bits - 1) & ~bits;
41 return bits >> 7;
42}
43
44/* The mask we created is directly usable as a bytemask */
45#define zero_bytemask(mask) (mask)
46
47static inline unsigned long find_zero(unsigned long mask)
48{
49 return count_masked_bytes(mask);
50}
51#endif
52
53#endif
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index b7b3f63299b0..b7cf6a547f11 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -1569,46 +1569,6 @@ ___clear_user_exit:
1569#endif /* CONFIG_MMU */ 1569#endif /* CONFIG_MMU */
1570 1570
1571/* 1571/*
1572 * extern long __strnlen_user(const char *__s, long __n)
1573 *
1574 * Inputs:
1575 * (r2) source address
1576 * (r3) source size in bytes
1577 *
1578 * Ouputs:
1579 * (r2) -EFAULT (in case of faulting)
1580 * string length (otherwise)
1581 */
1582 .global __strnlen_user
1583__strnlen_user:
1584 pta ___strnlen_user_set_reply, tr0
1585 pta ___strnlen_user1, tr1
1586 or ZERO, ZERO, r5 /* r5 = counter */
1587 movi -(EFAULT), r6 /* r6 = reply, no real fixup */
1588 or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
1589 beq r3, ZERO, tr0
1590
1591___strnlen_user1:
1592 ldx.b r2, r5, r7 /* Fault address: only in reading */
1593 addi r3, -1, r3 /* No real fixup */
1594 addi r5, 1, r5
1595 beq r3, ZERO, tr0
1596 bne r7, ZERO, tr1
1597! The line below used to be active. This meant led to a junk byte lying between each pair
1598! of entries in the argv & envp structures in memory. Whilst the program saw the right data
1599! via the argv and envp arguments to main, it meant the 'flat' representation visible through
1600! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example.
1601! addi r5, 1, r5 /* Include '\0' */
1602
1603___strnlen_user_set_reply:
1604 or r5, ZERO, r6 /* If done, return counter */
1605
1606___strnlen_user_exit:
1607 or r6, ZERO, r2
1608 ptabs LINK, tr0
1609 blink tr0, ZERO
1610
1611/*
1612 * extern long __get_user_asm_?(void *val, long addr) 1572 * extern long __get_user_asm_?(void *val, long addr)
1613 * 1573 *
1614 * Inputs: 1574 * Inputs:
@@ -1942,7 +1902,6 @@ asm_uaccess_start:
1942 .long ___copy_user2, ___copy_user_exit 1902 .long ___copy_user2, ___copy_user_exit
1943 .long ___clear_user1, ___clear_user_exit 1903 .long ___clear_user1, ___clear_user_exit
1944#endif 1904#endif
1945 .long ___strnlen_user1, ___strnlen_user_exit
1946 .long ___get_user_asm_b1, ___get_user_asm_b_exit 1905 .long ___get_user_asm_b1, ___get_user_asm_b_exit
1947 .long ___get_user_asm_w1, ___get_user_asm_w_exit 1906 .long ___get_user_asm_w1, ___get_user_asm_w_exit
1948 .long ___get_user_asm_l1, ___get_user_asm_l_exit 1907 .long ___get_user_asm_l1, ___get_user_asm_l_exit
diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c
index 3a3ba60e4f93..26a0774f5272 100644
--- a/arch/sh/kernel/sh_ksyms_64.c
+++ b/arch/sh/kernel/sh_ksyms_64.c
@@ -32,7 +32,6 @@ EXPORT_SYMBOL(__get_user_asm_b);
32EXPORT_SYMBOL(__get_user_asm_w); 32EXPORT_SYMBOL(__get_user_asm_w);
33EXPORT_SYMBOL(__get_user_asm_l); 33EXPORT_SYMBOL(__get_user_asm_l);
34EXPORT_SYMBOL(__get_user_asm_q); 34EXPORT_SYMBOL(__get_user_asm_q);
35EXPORT_SYMBOL(__strnlen_user);
36EXPORT_SYMBOL(__clear_user); 35EXPORT_SYMBOL(__clear_user);
37EXPORT_SYMBOL(copy_page); 36EXPORT_SYMBOL(copy_page);
38EXPORT_SYMBOL(__copy_user); 37EXPORT_SYMBOL(__copy_user);