diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-06-04 02:46:05 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-06-12 21:28:37 -0400 |
commit | cba8df4be3bdf10c86a26c458c5fc2ca978eeb2c (patch) | |
tree | 5dd9f6c93efc0588b813febe7d24178fa43d3d8b /arch/sh | |
parent | 0e100e11bd73be4e28e457cf5ad49a6892d5d1fe (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/Kconfig | 1 | ||||
-rw-r--r-- | arch/sh/include/asm/uaccess.h | 40 | ||||
-rw-r--r-- | arch/sh/include/asm/uaccess_32.h | 36 | ||||
-rw-r--r-- | arch/sh/include/asm/uaccess_64.h | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/word-at-a-time.h | 53 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh5/entry.S | 41 | ||||
-rw-r--r-- | arch/sh/kernel/sh_ksyms_64.c | 1 |
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 | ||
105 | extern long strncpy_from_user(char *dest, const char __user *src, long count); | 105 | extern long strncpy_from_user(char *dest, const char __user *src, long count); |
106 | 106 | ||
107 | extern __must_check long strlen_user(const char __user *str); | ||
108 | extern __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 | */ | ||
181 | static 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 | ||
171 | extern void __put_user_unknown(void); | 171 | extern 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 | */ | ||
177 | static 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); | |||
84 | extern long __put_user_asm_q(void *, long); | 84 | extern long __put_user_asm_q(void *, long); |
85 | extern void __put_user_unknown(void); | 85 | extern void __put_user_unknown(void); |
86 | 86 | ||
87 | extern 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 | */ | ||
10 | struct 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 */ | ||
17 | static 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 */ | ||
26 | static 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 | |||
33 | static 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 | |||
38 | static 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 | |||
47 | static 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); | |||
32 | EXPORT_SYMBOL(__get_user_asm_w); | 32 | EXPORT_SYMBOL(__get_user_asm_w); |
33 | EXPORT_SYMBOL(__get_user_asm_l); | 33 | EXPORT_SYMBOL(__get_user_asm_l); |
34 | EXPORT_SYMBOL(__get_user_asm_q); | 34 | EXPORT_SYMBOL(__get_user_asm_q); |
35 | EXPORT_SYMBOL(__strnlen_user); | ||
36 | EXPORT_SYMBOL(__clear_user); | 35 | EXPORT_SYMBOL(__clear_user); |
37 | EXPORT_SYMBOL(copy_page); | 36 | EXPORT_SYMBOL(copy_page); |
38 | EXPORT_SYMBOL(__copy_user); | 37 | EXPORT_SYMBOL(__copy_user); |