diff options
| -rw-r--r-- | arch/x86/include/asm/uaccess.h | 57 |
1 files changed, 14 insertions, 43 deletions
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index a8d12653f304..d710a2555fd6 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
| @@ -125,13 +125,12 @@ extern int __get_user_4(void); | |||
| 125 | extern int __get_user_8(void); | 125 | extern int __get_user_8(void); |
| 126 | extern int __get_user_bad(void); | 126 | extern int __get_user_bad(void); |
| 127 | 127 | ||
| 128 | #define __get_user_x(size, ret, x, ptr) \ | 128 | /* |
| 129 | asm volatile("call __get_user_" #size \ | 129 | * This is a type: either unsigned long, if the argument fits into |
| 130 | : "=a" (ret), "=d" (x) \ | 130 | * that type, or otherwise unsigned long long. |
| 131 | : "0" (ptr)) \ | 131 | */ |
| 132 | 132 | #define __inttype(x) \ | |
| 133 | /* Careful: we have to cast the result to the type of the pointer | 133 | __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) |
| 134 | * for sign reasons */ | ||
| 135 | 134 | ||
| 136 | /** | 135 | /** |
| 137 | * get_user: - Get a simple variable from user space. | 136 | * get_user: - Get a simple variable from user space. |
| @@ -149,48 +148,20 @@ extern int __get_user_bad(void); | |||
| 149 | * | 148 | * |
| 150 | * Returns zero on success, or -EFAULT on error. | 149 | * Returns zero on success, or -EFAULT on error. |
| 151 | * On error, the variable @x is set to zero. | 150 | * On error, the variable @x is set to zero. |
| 151 | * | ||
| 152 | * Careful: we have to cast the result to the type of the pointer | ||
| 153 | * for sign reasons. | ||
| 152 | */ | 154 | */ |
| 153 | #ifdef CONFIG_X86_32 | ||
| 154 | #define __get_user_8(ret, x, ptr) \ | ||
| 155 | do { \ | ||
| 156 | register unsigned long long __xx asm("%edx"); \ | ||
| 157 | asm volatile("call __get_user_8" \ | ||
| 158 | : "=a" (ret), "=r" (__xx) \ | ||
| 159 | : "0" (ptr)); \ | ||
| 160 | (x) = __xx; \ | ||
| 161 | } while (0) | ||
| 162 | |||
| 163 | #else | ||
| 164 | #define __get_user_8(__ret_gu, __val_gu, ptr) \ | ||
| 165 | __get_user_x(8, __ret_gu, __val_gu, ptr) | ||
| 166 | #endif | ||
| 167 | |||
| 168 | #define get_user(x, ptr) \ | 155 | #define get_user(x, ptr) \ |
| 169 | ({ \ | 156 | ({ \ |
| 170 | int __ret_gu; \ | 157 | int __ret_gu; \ |
| 171 | struct { \ | 158 | register __inttype(*(ptr)) __val_gu asm("%edx"); \ |
| 172 | unsigned long long __val_n : 8*sizeof(*(ptr)); \ | ||
| 173 | } __val_gu; \ | ||
| 174 | __chk_user_ptr(ptr); \ | 159 | __chk_user_ptr(ptr); \ |
| 175 | might_fault(); \ | 160 | might_fault(); \ |
| 176 | switch (sizeof(*(ptr))) { \ | 161 | asm volatile("call __get_user_%P3" \ |
| 177 | case 1: \ | 162 | : "=a" (__ret_gu), "=r" (__val_gu) \ |
| 178 | __get_user_x(1, __ret_gu, __val_gu.__val_n, ptr); \ | 163 | : "0" (ptr), "i" (sizeof(*(ptr)))); \ |
| 179 | break; \ | 164 | (x) = (__typeof__(*(ptr))) __val_gu; \ |
| 180 | case 2: \ | ||
| 181 | __get_user_x(2, __ret_gu, __val_gu.__val_n, ptr); \ | ||
| 182 | break; \ | ||
| 183 | case 4: \ | ||
| 184 | __get_user_x(4, __ret_gu, __val_gu.__val_n, ptr); \ | ||
| 185 | break; \ | ||
| 186 | case 8: \ | ||
| 187 | __get_user_8(__ret_gu, __val_gu.__val_n, ptr); \ | ||
| 188 | break; \ | ||
| 189 | default: \ | ||
| 190 | __get_user_x(X, __ret_gu, __val_gu.__val_n, ptr); \ | ||
| 191 | break; \ | ||
| 192 | } \ | ||
| 193 | (x) = (__typeof__(*(ptr)))__val_gu.__val_n; \ | ||
| 194 | __ret_gu; \ | 165 | __ret_gu; \ |
| 195 | }) | 166 | }) |
| 196 | 167 | ||
