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 | ||