diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-05-25 00:02:48 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-06-12 21:28:16 -0400 |
commit | 0e100e11bd73be4e28e457cf5ad49a6892d5d1fe (patch) | |
tree | 55e193c2f37f458bd51d363bac78e20897c86b49 /arch | |
parent | 94fa83c424321189ca24fb6cb4c0d224cdedc72d (diff) |
sh: switch to generic strncpy_from_user().
This kills off the special sh32/64 versions and adopts the generic
version. It should be possible to optimize this for SH-4A unaligned
loads, but this is a corner case that can be supported incrementally.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/Kconfig | 1 | ||||
-rw-r--r-- | arch/sh/include/asm/uaccess.h | 35 | ||||
-rw-r--r-- | arch/sh/include/asm/uaccess_32.h | 39 | ||||
-rw-r--r-- | arch/sh/include/asm/uaccess_64.h | 2 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh5/entry.S | 41 | ||||
-rw-r--r-- | arch/sh/kernel/sh_ksyms_64.c | 1 |
6 files changed, 5 insertions, 114 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 99bcd0ee838d..cbffc26c0434 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -32,6 +32,7 @@ config SUPERH | |||
32 | select GENERIC_SMP_IDLE_THREAD | 32 | select GENERIC_SMP_IDLE_THREAD |
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 | help | 36 | help |
36 | The SuperH is a RISC processor targeted for use in embedded systems | 37 | The SuperH is a RISC processor targeted for use in embedded systems |
37 | and consumer electronics; it was also used in the Sega Dreamcast | 38 | 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 050f221fa898..3df7eee9c155 100644 --- a/arch/sh/include/asm/uaccess.h +++ b/arch/sh/include/asm/uaccess.h | |||
@@ -25,6 +25,8 @@ | |||
25 | (__chk_user_ptr(addr), \ | 25 | (__chk_user_ptr(addr), \ |
26 | __access_ok((unsigned long __force)(addr), (size))) | 26 | __access_ok((unsigned long __force)(addr), (size))) |
27 | 27 | ||
28 | #define user_addr_max() (current_thread_info()->addr_limit.seg) | ||
29 | |||
28 | /* | 30 | /* |
29 | * Uh, these should become the main single-value transfer routines ... | 31 | * Uh, these should become the main single-value transfer routines ... |
30 | * They automatically use the right size if we just have the right | 32 | * They automatically use the right size if we just have the right |
@@ -100,6 +102,8 @@ struct __large_struct { unsigned long buf[100]; }; | |||
100 | # include "uaccess_64.h" | 102 | # include "uaccess_64.h" |
101 | #endif | 103 | #endif |
102 | 104 | ||
105 | extern long strncpy_from_user(char *dest, const char __user *src, long count); | ||
106 | |||
103 | /* Generic arbitrary sized copy. */ | 107 | /* Generic arbitrary sized copy. */ |
104 | /* Return the number of bytes NOT copied */ | 108 | /* Return the number of bytes NOT copied */ |
105 | __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); | 109 | __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); |
@@ -137,37 +141,6 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size); | |||
137 | __cl_size; \ | 141 | __cl_size; \ |
138 | }) | 142 | }) |
139 | 143 | ||
140 | /** | ||
141 | * strncpy_from_user: - Copy a NUL terminated string from userspace. | ||
142 | * @dst: Destination address, in kernel space. This buffer must be at | ||
143 | * least @count bytes long. | ||
144 | * @src: Source address, in user space. | ||
145 | * @count: Maximum number of bytes to copy, including the trailing NUL. | ||
146 | * | ||
147 | * Copies a NUL-terminated string from userspace to kernel space. | ||
148 | * | ||
149 | * On success, returns the length of the string (not including the trailing | ||
150 | * NUL). | ||
151 | * | ||
152 | * If access to userspace fails, returns -EFAULT (some data may have been | ||
153 | * copied). | ||
154 | * | ||
155 | * If @count is smaller than the length of the string, copies @count bytes | ||
156 | * and returns @count. | ||
157 | */ | ||
158 | #define strncpy_from_user(dest,src,count) \ | ||
159 | ({ \ | ||
160 | unsigned long __sfu_src = (unsigned long)(src); \ | ||
161 | int __sfu_count = (int)(count); \ | ||
162 | long __sfu_res = -EFAULT; \ | ||
163 | \ | ||
164 | if (__access_ok(__sfu_src, __sfu_count)) \ | ||
165 | __sfu_res = __strncpy_from_user((unsigned long)(dest), \ | ||
166 | __sfu_src, __sfu_count); \ | ||
167 | \ | ||
168 | __sfu_res; \ | ||
169 | }) | ||
170 | |||
171 | static inline unsigned long | 144 | static inline unsigned long |
172 | copy_from_user(void *to, const void __user *from, unsigned long n) | 145 | copy_from_user(void *to, const void __user *from, unsigned long n) |
173 | { | 146 | { |
diff --git a/arch/sh/include/asm/uaccess_32.h b/arch/sh/include/asm/uaccess_32.h index ae0d24f6653f..ef44d05bb631 100644 --- a/arch/sh/include/asm/uaccess_32.h +++ b/arch/sh/include/asm/uaccess_32.h | |||
@@ -170,45 +170,6 @@ __asm__ __volatile__( \ | |||
170 | 170 | ||
171 | extern void __put_user_unknown(void); | 171 | extern void __put_user_unknown(void); |
172 | 172 | ||
173 | static inline int | ||
174 | __strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) | ||
175 | { | ||
176 | __kernel_size_t res; | ||
177 | unsigned long __dummy, _d, _s, _c; | ||
178 | |||
179 | __asm__ __volatile__( | ||
180 | "9:\n" | ||
181 | "mov.b @%2+, %1\n\t" | ||
182 | "cmp/eq #0, %1\n\t" | ||
183 | "bt/s 2f\n" | ||
184 | "1:\n" | ||
185 | "mov.b %1, @%3\n\t" | ||
186 | "dt %4\n\t" | ||
187 | "bf/s 9b\n\t" | ||
188 | " add #1, %3\n\t" | ||
189 | "2:\n\t" | ||
190 | "sub %4, %0\n" | ||
191 | "3:\n" | ||
192 | ".section .fixup,\"ax\"\n" | ||
193 | "4:\n\t" | ||
194 | "mov.l 5f, %1\n\t" | ||
195 | "jmp @%1\n\t" | ||
196 | " mov %9, %0\n\t" | ||
197 | ".balign 4\n" | ||
198 | "5: .long 3b\n" | ||
199 | ".previous\n" | ||
200 | ".section __ex_table,\"a\"\n" | ||
201 | " .balign 4\n" | ||
202 | " .long 9b,4b\n" | ||
203 | ".previous" | ||
204 | : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c) | ||
205 | : "0" (__count), "2" (__src), "3" (__dest), "4" (__count), | ||
206 | "i" (-EFAULT) | ||
207 | : "memory", "t"); | ||
208 | |||
209 | return res; | ||
210 | } | ||
211 | |||
212 | /* | 173 | /* |
213 | * Return the size of a string (including the ending 0 even when we have | 174 | * Return the size of a string (including the ending 0 even when we have |
214 | * exceeded the maximum string length). | 175 | * exceeded the maximum string length). |
diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h index 56fd20b8cdcc..0042c9054b20 100644 --- a/arch/sh/include/asm/uaccess_64.h +++ b/arch/sh/include/asm/uaccess_64.h | |||
@@ -85,7 +85,5 @@ 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); | 87 | extern long __strnlen_user(const char *__s, long __n); |
88 | extern int __strncpy_from_user(unsigned long __dest, | ||
89 | unsigned long __user __src, int __count); | ||
90 | 88 | ||
91 | #endif /* __ASM_SH_UACCESS_64_H */ | 89 | #endif /* __ASM_SH_UACCESS_64_H */ |
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index ff1f0e6e9bec..b7b3f63299b0 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 | * int __strncpy_from_user(unsigned long __dest, unsigned long __src, | ||
1573 | * int __count) | ||
1574 | * | ||
1575 | * Inputs: | ||
1576 | * (r2) target address | ||
1577 | * (r3) source address | ||
1578 | * (r4) maximum size in bytes | ||
1579 | * | ||
1580 | * Ouputs: | ||
1581 | * (*r2) copied data | ||
1582 | * (r2) -EFAULT (in case of faulting) | ||
1583 | * copied data (otherwise) | ||
1584 | */ | ||
1585 | .global __strncpy_from_user | ||
1586 | __strncpy_from_user: | ||
1587 | pta ___strncpy_from_user1, tr0 | ||
1588 | pta ___strncpy_from_user_done, tr1 | ||
1589 | or r4, ZERO, r5 /* r5 = original count */ | ||
1590 | beq/u r4, r63, tr1 /* early exit if r4==0 */ | ||
1591 | movi -(EFAULT), r6 /* r6 = reply, no real fixup */ | ||
1592 | or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ | ||
1593 | |||
1594 | ___strncpy_from_user1: | ||
1595 | ld.b r3, 0, r7 /* Fault address: only in reading */ | ||
1596 | st.b r2, 0, r7 | ||
1597 | addi r2, 1, r2 | ||
1598 | addi r3, 1, r3 | ||
1599 | beq/u ZERO, r7, tr1 | ||
1600 | addi r4, -1, r4 /* return real number of copied bytes */ | ||
1601 | bne/l ZERO, r4, tr0 | ||
1602 | |||
1603 | ___strncpy_from_user_done: | ||
1604 | sub r5, r4, r6 /* If done, return copied */ | ||
1605 | |||
1606 | ___strncpy_from_user_exit: | ||
1607 | or r6, ZERO, r2 | ||
1608 | ptabs LINK, tr0 | ||
1609 | blink tr0, ZERO | ||
1610 | |||
1611 | /* | ||
1612 | * extern long __strnlen_user(const char *__s, long __n) | 1572 | * extern long __strnlen_user(const char *__s, long __n) |
1613 | * | 1573 | * |
1614 | * Inputs: | 1574 | * Inputs: |
@@ -1982,7 +1942,6 @@ asm_uaccess_start: | |||
1982 | .long ___copy_user2, ___copy_user_exit | 1942 | .long ___copy_user2, ___copy_user_exit |
1983 | .long ___clear_user1, ___clear_user_exit | 1943 | .long ___clear_user1, ___clear_user_exit |
1984 | #endif | 1944 | #endif |
1985 | .long ___strncpy_from_user1, ___strncpy_from_user_exit | ||
1986 | .long ___strnlen_user1, ___strnlen_user_exit | 1945 | .long ___strnlen_user1, ___strnlen_user_exit |
1987 | .long ___get_user_asm_b1, ___get_user_asm_b_exit | 1946 | .long ___get_user_asm_b1, ___get_user_asm_b_exit |
1988 | .long ___get_user_asm_w1, ___get_user_asm_w_exit | 1947 | .long ___get_user_asm_w1, ___get_user_asm_w_exit |
diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index 45afa5c51f67..3a3ba60e4f93 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c | |||
@@ -33,7 +33,6 @@ 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); | 35 | EXPORT_SYMBOL(__strnlen_user); |
36 | EXPORT_SYMBOL(__strncpy_from_user); | ||
37 | EXPORT_SYMBOL(__clear_user); | 36 | EXPORT_SYMBOL(__clear_user); |
38 | EXPORT_SYMBOL(copy_page); | 37 | EXPORT_SYMBOL(copy_page); |
39 | EXPORT_SYMBOL(__copy_user); | 38 | EXPORT_SYMBOL(__copy_user); |