aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2016-02-04 11:54:45 -0500
committerRussell King <rmk+kernel@armlinux.org.uk>2016-06-22 14:55:11 -0400
commit9f73bd8bb445e0cbe4bcef6d4cfc788f1e184007 (patch)
treee252451345e484c135113d8274fdc8437cf9377b
parent9f85eae622cd9b63dc44b7dcfa958b3881a09cbb (diff)
ARM: uaccess: remove put_user() code duplication
Remove the code duplication between put_user() and __put_user(). The code which selected the implementation based upon the pointer size, and declared the local variable to hold the value to be put are common to both implementations. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/uaccess.h106
1 files changed, 49 insertions, 57 deletions
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 7badc3e55109..62a6f65029e6 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -230,49 +230,23 @@ extern int __put_user_2(void *, unsigned int);
230extern int __put_user_4(void *, unsigned int); 230extern int __put_user_4(void *, unsigned int);
231extern int __put_user_8(void *, unsigned long long); 231extern int __put_user_8(void *, unsigned long long);
232 232
233#define __put_user_x(__r2, __p, __e, __l, __s) \ 233#define __put_user_check(__pu_val, __ptr, __err, __s) \
234 __asm__ __volatile__ ( \
235 __asmeq("%0", "r0") __asmeq("%2", "r2") \
236 __asmeq("%3", "r1") \
237 "bl __put_user_" #__s \
238 : "=&r" (__e) \
239 : "0" (__p), "r" (__r2), "r" (__l) \
240 : "ip", "lr", "cc")
241
242#define __put_user_check(x, p) \
243 ({ \ 234 ({ \
244 unsigned long __limit = current_thread_info()->addr_limit - 1; \ 235 unsigned long __limit = current_thread_info()->addr_limit - 1; \
245 const typeof(*(p)) __user *__tmp_p = (p); \ 236 register typeof(__pu_val) __r2 asm("r2") = __pu_val; \
246 register const typeof(*(p)) __r2 asm("r2") = (x); \ 237 register const void __user *__p asm("r0") = __ptr; \
247 register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
248 register unsigned long __l asm("r1") = __limit; \ 238 register unsigned long __l asm("r1") = __limit; \
249 register int __e asm("r0"); \ 239 register int __e asm("r0"); \
250 unsigned int __ua_flags = uaccess_save_and_enable(); \ 240 __asm__ __volatile__ ( \
251 switch (sizeof(*(__p))) { \ 241 __asmeq("%0", "r0") __asmeq("%2", "r2") \
252 case 1: \ 242 __asmeq("%3", "r1") \
253 __put_user_x(__r2, __p, __e, __l, 1); \ 243 "bl __put_user_" #__s \
254 break; \ 244 : "=&r" (__e) \
255 case 2: \ 245 : "0" (__p), "r" (__r2), "r" (__l) \
256 __put_user_x(__r2, __p, __e, __l, 2); \ 246 : "ip", "lr", "cc"); \
257 break; \ 247 __err = __e; \
258 case 4: \
259 __put_user_x(__r2, __p, __e, __l, 4); \
260 break; \
261 case 8: \
262 __put_user_x(__r2, __p, __e, __l, 8); \
263 break; \
264 default: __e = __put_user_bad(); break; \
265 } \
266 uaccess_restore(__ua_flags); \
267 __e; \
268 }) 248 })
269 249
270#define put_user(x, p) \
271 ({ \
272 might_fault(); \
273 __put_user_check(x, p); \
274 })
275
276#else /* CONFIG_MMU */ 250#else /* CONFIG_MMU */
277 251
278/* 252/*
@@ -290,7 +264,7 @@ static inline void set_fs(mm_segment_t fs)
290} 264}
291 265
292#define get_user(x, p) __get_user(x, p) 266#define get_user(x, p) __get_user(x, p)
293#define put_user(x, p) __put_user(x, p) 267#define __put_user_check __put_user_nocheck
294 268
295#endif /* CONFIG_MMU */ 269#endif /* CONFIG_MMU */
296 270
@@ -381,36 +355,54 @@ do { \
381#define __get_user_asm_word(x, addr, err) \ 355#define __get_user_asm_word(x, addr, err) \
382 __get_user_asm(x, addr, err, ldr) 356 __get_user_asm(x, addr, err, ldr)
383 357
358
359#define __put_user_switch(x, ptr, __err, __fn) \
360 do { \
361 const __typeof__(*(ptr)) __user *__pu_ptr = (ptr); \
362 __typeof__(*(ptr)) __pu_val = (x); \
363 unsigned int __ua_flags; \
364 might_fault(); \
365 __ua_flags = uaccess_save_and_enable(); \
366 switch (sizeof(*(ptr))) { \
367 case 1: __fn(__pu_val, __pu_ptr, __err, 1); break; \
368 case 2: __fn(__pu_val, __pu_ptr, __err, 2); break; \
369 case 4: __fn(__pu_val, __pu_ptr, __err, 4); break; \
370 case 8: __fn(__pu_val, __pu_ptr, __err, 8); break; \
371 default: __err = __put_user_bad(); break; \
372 } \
373 uaccess_restore(__ua_flags); \
374 } while (0)
375
376#define put_user(x, ptr) \
377({ \
378 int __pu_err = 0; \
379 __put_user_switch((x), (ptr), __pu_err, __put_user_check); \
380 __pu_err; \
381})
382
384#define __put_user(x, ptr) \ 383#define __put_user(x, ptr) \
385({ \ 384({ \
386 long __pu_err = 0; \ 385 long __pu_err = 0; \
387 __put_user_err((x), (ptr), __pu_err); \ 386 __put_user_switch((x), (ptr), __pu_err, __put_user_nocheck); \
388 __pu_err; \ 387 __pu_err; \
389}) 388})
390 389
391#define __put_user_error(x, ptr, err) \ 390#define __put_user_error(x, ptr, err) \
392({ \ 391({ \
393 __put_user_err((x), (ptr), err); \ 392 __put_user_switch((x), (ptr), (err), __put_user_nocheck); \
394 (void) 0; \ 393 (void) 0; \
395}) 394})
396 395
397#define __put_user_err(x, ptr, err) \ 396#define __put_user_nocheck(x, __pu_ptr, __err, __size) \
398do { \ 397 do { \
399 unsigned long __pu_addr = (unsigned long)(ptr); \ 398 unsigned long __pu_addr = (unsigned long)__pu_ptr; \
400 unsigned int __ua_flags; \ 399 __put_user_nocheck_##__size(x, __pu_addr, __err); \
401 __typeof__(*(ptr)) __pu_val = (x); \ 400 } while (0)
402 __chk_user_ptr(ptr); \ 401
403 might_fault(); \ 402#define __put_user_nocheck_1 __put_user_asm_byte
404 __ua_flags = uaccess_save_and_enable(); \ 403#define __put_user_nocheck_2 __put_user_asm_half
405 switch (sizeof(*(ptr))) { \ 404#define __put_user_nocheck_4 __put_user_asm_word
406 case 1: __put_user_asm_byte(__pu_val, __pu_addr, err); break; \ 405#define __put_user_nocheck_8 __put_user_asm_dword
407 case 2: __put_user_asm_half(__pu_val, __pu_addr, err); break; \
408 case 4: __put_user_asm_word(__pu_val, __pu_addr, err); break; \
409 case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break; \
410 default: __put_user_bad(); \
411 } \
412 uaccess_restore(__ua_flags); \
413} while (0)
414 406
415#define __put_user_asm(x, __pu_addr, err, instr) \ 407#define __put_user_asm(x, __pu_addr, err, instr) \
416 __asm__ __volatile__( \ 408 __asm__ __volatile__( \