aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2010-03-22 11:22:41 -0400
committerMichal Simek <monstr@monstr.eu>2010-04-01 02:38:22 -0400
commitef4e277b5d86e56db650137de0b1cd16ded32498 (patch)
tree4a8b2d6a716b9a3aad8e43c5670628e7e005f3cd /arch/microblaze
parent3a6d77245efe062993284fd1c2f7510d9a90efe1 (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>
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/include/asm/uaccess.h78
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) \
217extern 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