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/sh/include | |
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/sh/include')
-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 |
3 files changed, 4 insertions, 72 deletions
diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h index 050f221fa89..3df7eee9c15 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 ae0d24f6653..ef44d05bb63 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 56fd20b8cdc..0042c9054b2 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 */ |