Commit 235944be authored by Russell King's avatar Russell King

[ARM] Fix up {__,}put_user macros

- Make them work on 64-bit quantities
- clean up use of local pointers to prevent multiple references
  to the pointer (which may have side effects.)

Note that this causes __put_user to produce a warning each time
a pointer is passed as the first argument, since the 64-bit
implementation tries to cast a 32-bit pointer to a 64-bit long.

The fix for this warning waiting for comments from the GCC
community.
parent 3e393f8f
......@@ -37,7 +37,7 @@ static inline void set_fs (mm_segment_t fs)
: "cc"); \
(flag == 0); })
#define __put_user_asm_byte(x,addr,err) \
#define __put_user_asm_byte(x,__pu_addr,err) \
__asm__ __volatile__( \
"1: strbt %1,[%2],#0\n" \
"2:\n" \
......@@ -51,27 +51,26 @@ static inline void set_fs (mm_segment_t fs)
" .long 1b, 3b\n" \
" .previous" \
: "=r" (err) \
: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
: "r" (x), "r" (__pu_addr), "i" (-EFAULT), "0" (err) \
: "cc")
#ifndef __ARMEB__
#define __put_user_asm_half(x,addr,err) \
#define __put_user_asm_half(x,__pu_addr,err) \
({ \
unsigned long __temp = (unsigned long)(x); \
unsigned long __ptr = (unsigned long)(addr); \
__put_user_asm_byte(__temp, __ptr, err); \
__put_user_asm_byte(__temp >> 8, __ptr + 1, err); \
__put_user_asm_byte(__temp, __pu_addr, err); \
__put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
})
#else
#define __put_user_asm_half(x,addr,err) \
#define __put_user_asm_half(x,__pu_addr,err) \
({ \
unsigned long __temp = (unsigned long)(x); \
unsigned long __ptr = (unsigned long)(addr); \
__put_user_asm_byte(__temp >> 8, __ptr, err); \
__put_user_asm_byte(__temp, __ptr + 1, err); \
__put_user_asm_byte(__temp >> 8, __pu_addr, err); \
__put_user_asm_byte(__temp, __pu_addr + 1, err); \
})
#endif
#define __put_user_asm_word(x,addr,err) \
#define __put_user_asm_word(x,__pu_addr,err) \
__asm__ __volatile__( \
"1: strt %1,[%2],#0\n" \
"2:\n" \
......@@ -85,7 +84,31 @@ static inline void set_fs (mm_segment_t fs)
" .long 1b, 3b\n" \
" .previous" \
: "=r" (err) \
: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
: "r" (x), "r" (__pu_addr), "i" (-EFAULT), "0" (err))
#define __put_user_asm_dword(x,__pu_addr,err) \
({ \
unsigned long long __temp = (unsigned long long)x; \
__asm__ __volatile__( \
"1: strt %1, [%2], #0\n" \
"2: strt %3, [%4], #0\n" \
"3:\n" \
" .section .fixup,\"ax\"\n" \
" .align 2\n" \
"4: mov %0, %5\n" \
" b 3b\n" \
" .previous\n" \
" .section __ex_table,\"a\"\n" \
" .align 3\n" \
" .long 1b, 4b\n" \
" .long 2b, 4b\n" \
" .previous" \
: "=r" (err) \
: "r" (__temp), "r" (__pu_addr), \
"r" (__temp >> 32), "r" (__pu_addr + 4), \
"i" (-EFAULT), "0" (err) \
: "cc"); \
})
#define __get_user_asm_byte(x,addr,err) \
__asm__ __volatile__( \
......
......@@ -81,7 +81,7 @@ extern int __get_user_bad(void);
const register typeof(*(p)) *__p asm("r0") = (p); \
register typeof(*(p)) __r1 asm("r1"); \
register int __e asm("r0"); \
switch (sizeof(*(p))) { \
switch (sizeof(*(__p))) { \
case 1: \
__get_user_x(__r1, __p, __e, 1, "lr"); \
break; \
......@@ -120,7 +120,7 @@ extern int __put_user_bad(void);
const register typeof(*(p)) __r1 asm("r1") = (x); \
const register typeof(*(p)) *__p asm("r0") = (p); \
register int __e asm("r0"); \
switch (sizeof(*(p))) { \
switch (sizeof(*(__p))) { \
case 1: \
__put_user_x(__r1, __p, __e, 1, "r2", "lr"); \
break; \
......@@ -256,14 +256,15 @@ static inline long strnlen_user(const char *s, long n)
#define __put_user_nocheck(x,ptr,size) \
({ \
long __pu_err = 0; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
unsigned long __pu_addr = (unsigned long)(ptr); \
__put_user_size((x),__pu_addr,(size),__pu_err); \
__pu_err; \
})
#define __put_user_nocheck_error(x,ptr,size,err) \
({ \
__put_user_size((x),(ptr),(size),err); \
unsigned long __pu_addr = (unsigned long)(ptr); \
__put_user_size((x),__pu_addr,(size),err); \
(void) 0; \
})
......@@ -273,6 +274,7 @@ do { \
case 1: __get_user_asm_byte(x,ptr,retval); break; \
case 2: __get_user_asm_half(x,ptr,retval); break; \
case 4: __get_user_asm_word(x,ptr,retval); break; \
case 8: __get_user_asm_dword(x,ptr,retval); break; \
default: (x) = __get_user_bad(); \
} \
} while (0)
......@@ -283,6 +285,7 @@ do { \
case 1: __put_user_asm_byte(x,ptr,retval); break; \
case 2: __put_user_asm_half(x,ptr,retval); break; \
case 4: __put_user_asm_word(x,ptr,retval); break; \
case 8: __put_user_asm_dword(x,ptr,retval); break; \
default: __put_user_bad(); \
} \
} while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment