diff options
| author | Michal Simek <monstr@monstr.eu> | 2010-03-22 11:22:41 -0400 |
|---|---|---|
| committer | Michal Simek <monstr@monstr.eu> | 2010-04-01 02:38:22 -0400 |
| commit | ef4e277b5d86e56db650137de0b1cd16ded32498 (patch) | |
| tree | 4a8b2d6a716b9a3aad8e43c5670628e7e005f3cd | |
| parent | 3a6d77245efe062993284fd1c2f7510d9a90efe1 (diff) | |
microblaze: uaccess: Fix put_user for noMMU
Here is small regression on dhrystone tests and I think
that on all benchmarking tests. It is due to better checking
mechanism in put_user macro
Signed-off-by: Michal Simek <monstr@monstr.eu>
| -rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index b079ac31a671..4f17950d0a0e 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
| @@ -213,32 +213,66 @@ extern long __user_bad(void); | |||
| 213 | ? __get_user((x), (ptr)) : -EFAULT; \ | 213 | ? __get_user((x), (ptr)) : -EFAULT; \ |
| 214 | }) | 214 | }) |
| 215 | 215 | ||
| 216 | /* Undefined function to trigger linker error */ | 216 | #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ |
| 217 | extern int bad_user_access_length(void); | 217 | ({ \ |
| 218 | __asm__ __volatile__ ( \ | ||
| 219 | "1:" insn " %1, %2, r0;" \ | ||
| 220 | " addk %0, r0, r0;" \ | ||
| 221 | "2: " \ | ||
| 222 | __FIXUP_SECTION \ | ||
| 223 | "3: brid 2b;" \ | ||
| 224 | " addik %0, r0, %3;" \ | ||
| 225 | ".previous;" \ | ||
| 226 | __EX_TABLE_SECTION \ | ||
| 227 | ".word 1b,3b;" \ | ||
| 228 | ".previous;" \ | ||
| 229 | : "=&r"(__gu_err) \ | ||
| 230 | : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \ | ||
| 231 | ); \ | ||
| 232 | }) | ||
| 218 | 233 | ||
| 219 | /* FIXME is not there defined __pu_val */ | 234 | #define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err) \ |
| 220 | #define __put_user(var, ptr) \ | ||
| 221 | ({ \ | 235 | ({ \ |
| 222 | int __pu_err = 0; \ | 236 | __asm__ __volatile__ (" lwi %0, %1, 0;" \ |
| 223 | switch (sizeof(*(ptr))) { \ | 237 | "1: swi %0, %2, 0;" \ |
| 224 | case 1: \ | 238 | " lwi %0, %1, 4;" \ |
| 225 | case 2: \ | 239 | "2: swi %0, %2, 4;" \ |
| 226 | case 4: \ | 240 | " addk %0, r0, r0;" \ |
| 227 | *(ptr) = (var); \ | 241 | "3: " \ |
| 228 | break; \ | 242 | __FIXUP_SECTION \ |
| 229 | case 8: { \ | 243 | "4: brid 3b;" \ |
| 230 | typeof(*(ptr)) __pu_val = (var); \ | 244 | " addik %0, r0, %3;" \ |
| 231 | memcpy(ptr, &__pu_val, sizeof(__pu_val)); \ | 245 | ".previous;" \ |
| 232 | } \ | 246 | __EX_TABLE_SECTION \ |
| 233 | break; \ | 247 | ".word 1b,4b,2b,4b;" \ |
| 234 | default: \ | 248 | ".previous;" \ |
| 235 | __pu_err = __put_user_bad(); \ | 249 | : "=&r"(__gu_err) \ |
| 236 | break; \ | 250 | : "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \ |
| 237 | } \ | 251 | ); \ |
| 238 | __pu_err; \ | ||
| 239 | }) | 252 | }) |
| 240 | 253 | ||
| 241 | #define __put_user_bad() (bad_user_access_length(), (-EFAULT)) | 254 | #define __put_user(x, ptr) \ |
| 255 | ({ \ | ||
| 256 | __typeof__(*(ptr)) volatile __gu_val = (x); \ | ||
| 257 | long __gu_err = 0; \ | ||
| 258 | switch (sizeof(__gu_val)) { \ | ||
| 259 | case 1: \ | ||
| 260 | __put_user_asm("sb", (ptr), __gu_val, __gu_err); \ | ||
| 261 | break; \ | ||
| 262 | case 2: \ | ||
| 263 | __put_user_asm("sh", (ptr), __gu_val, __gu_err); \ | ||
| 264 | break; \ | ||
| 265 | case 4: \ | ||
| 266 | __put_user_asm("sw", (ptr), __gu_val, __gu_err); \ | ||
| 267 | break; \ | ||
| 268 | case 8: \ | ||
| 269 | __put_user_asm_8((ptr), __gu_val, __gu_err); \ | ||
| 270 | break; \ | ||
| 271 | default: \ | ||
| 272 | /*__gu_err = -EINVAL;*/ __gu_err = __user_bad(); \ | ||
| 273 | } \ | ||
| 274 | __gu_err; \ | ||
| 275 | }) | ||
| 242 | 276 | ||
| 243 | #define put_user(x, ptr) __put_user((x), (ptr)) | 277 | #define put_user(x, ptr) __put_user((x), (ptr)) |
| 244 | 278 | ||
