aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2012-09-07 14:23:27 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2012-09-07 15:54:38 +0100
commit373a6e24c6152096be1d540469be3aa19bb521c8 (patch)
tree8379481c894faae487d96f699532b261f3084f4a
parent632cb4ad190de8ede04fe1530b3561726d9c55fa (diff)
downloadlinux-aarch64-373a6e24c6152096be1d540469be3aa19bb521c8.tar.gz
arm64: Ensure correct casting for get_user/put_user arguments
There may be cases where sizeof(x) != sizeof(*ptr) and this confuses the compiler. This patch makes the conversion to/from "unsigned long" for get_user as that's what the inline asm expects. For put_user, it makes the conversion to __typeof__(*ptr). Most of the times, the compiler will just ignore these and not generate additional code. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/include/asm/uaccess.h19
1 files changed, 11 insertions, 8 deletions
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index cdc1666e47f..008f8481da6 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -128,23 +128,25 @@ static inline void set_fs(mm_segment_t fs)
#define __get_user_err(x, ptr, err) \
do { \
+ unsigned long __gu_val; \
__chk_user_ptr(ptr); \
switch (sizeof(*(ptr))) { \
case 1: \
- __get_user_asm("ldrb", "%w", (x), (ptr), (err)); \
+ __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \
break; \
case 2: \
- __get_user_asm("ldrh", "%w", (x), (ptr), (err)); \
+ __get_user_asm("ldrh", "%w", __gu_val, (ptr), (err)); \
break; \
case 4: \
- __get_user_asm("ldr", "%w", (x), (ptr), (err)); \
+ __get_user_asm("ldr", "%w", __gu_val, (ptr), (err)); \
break; \
case 8: \
- __get_user_asm("ldr", "%", (x), (ptr), (err)); \
+ __get_user_asm("ldr", "%", __gu_val, (ptr), (err)); \
break; \
default: \
BUILD_BUG(); \
} \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
} while (0)
#define __get_user(x, ptr) \
@@ -188,19 +190,20 @@ do { \
#define __put_user_err(x, ptr, err) \
do { \
+ __typeof__(*(ptr)) __pu_val = (x); \
__chk_user_ptr(ptr); \
switch (sizeof(*(ptr))) { \
case 1: \
- __put_user_asm("strb", "%w", (x), (ptr), (err)); \
+ __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \
break; \
case 2: \
- __put_user_asm("strh", "%w", (x), (ptr), (err)); \
+ __put_user_asm("strh", "%w", __pu_val, (ptr), (err)); \
break; \
case 4: \
- __put_user_asm("str", "%w", (x), (ptr), (err)); \
+ __put_user_asm("str", "%w", __pu_val, (ptr), (err)); \
break; \
case 8: \
- __put_user_asm("str", "%", (x), (ptr), (err)); \
+ __put_user_asm("str", "%", __pu_val, (ptr), (err)); \
break; \
default: \
BUILD_BUG(); \