diff options
author | Michal Simek <monstr@monstr.eu> | 2010-03-05 10:50:01 -0500 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-04-01 02:38:20 -0400 |
commit | 40b1156db09ab2df48aa4970ddf4a27a17246f1f (patch) | |
tree | b9c3432203d89d0db621497c189b05c052990973 /arch/microblaze/include/asm | |
parent | 60a729f7bb936a9ab82b430de70a1952f560adf3 (diff) |
microblaze: uaccess: fix clean user macro
This is the first patch which does uaccess unification.
I choosed to do several patches to be able to use bisect
in future if any fault happens.
Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze/include/asm')
-rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index ce5defb259a4..fdb1c1cf51ad 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
@@ -71,8 +71,6 @@ struct exception_table_entry { | |||
71 | unsigned long insn, fixup; | 71 | unsigned long insn, fixup; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | #define __clear_user(addr, n) (memset((void *)(addr), 0, (n)), 0) | ||
75 | |||
76 | #ifndef CONFIG_MMU | 74 | #ifndef CONFIG_MMU |
77 | 75 | ||
78 | /* Check against bounds of physical memory */ | 76 | /* Check against bounds of physical memory */ |
@@ -86,7 +84,31 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) | |||
86 | ___range_ok((unsigned long)(addr), (unsigned long)(size)) | 84 | ___range_ok((unsigned long)(addr), (unsigned long)(size)) |
87 | 85 | ||
88 | #define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0) | 86 | #define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0) |
89 | #define __access_ok(add, size) (__range_ok((addr), (size)) == 0) | 87 | |
88 | #else | ||
89 | |||
90 | /* | ||
91 | * Address is valid if: | ||
92 | * - "addr", "addr + size" and "size" are all below the limit | ||
93 | */ | ||
94 | #define access_ok(type, addr, size) \ | ||
95 | (get_fs().seg > (((unsigned long)(addr)) | \ | ||
96 | (size) | ((unsigned long)(addr) + (size)))) | ||
97 | |||
98 | /* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n", | ||
99 | type?"WRITE":"READ",addr,size,get_fs().seg)) */ | ||
100 | |||
101 | #endif | ||
102 | |||
103 | #ifdef CONFIG_MMU | ||
104 | # define __FIXUP_SECTION ".section .fixup,\"ax\"\n" | ||
105 | # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n" | ||
106 | #else | ||
107 | # define __FIXUP_SECTION ".section .discard,\"ax\"\n" | ||
108 | # define __EX_TABLE_SECTION ".section .discard,\"a\"\n" | ||
109 | #endif | ||
110 | |||
111 | #ifndef CONFIG_MMU | ||
90 | 112 | ||
91 | /* Undefined function to trigger linker error */ | 113 | /* Undefined function to trigger linker error */ |
92 | extern int bad_user_access_length(void); | 114 | extern int bad_user_access_length(void); |
@@ -151,6 +173,9 @@ extern int bad_user_access_length(void); | |||
151 | #define __copy_from_user_inatomic(to, from, n) \ | 173 | #define __copy_from_user_inatomic(to, from, n) \ |
152 | (__copy_from_user((to), (from), (n))) | 174 | (__copy_from_user((to), (from), (n))) |
153 | 175 | ||
176 | #define __clear_user(addr, n) (memset((void *)(addr), 0, (n)), 0) | ||
177 | |||
178 | /* stejne s MMU */ | ||
154 | static inline unsigned long clear_user(void *addr, unsigned long size) | 179 | static inline unsigned long clear_user(void *addr, unsigned long size) |
155 | { | 180 | { |
156 | if (access_ok(VERIFY_WRITE, addr, size)) | 181 | if (access_ok(VERIFY_WRITE, addr, size)) |
@@ -167,17 +192,6 @@ extern long strnlen_user(const char *src, long count); | |||
167 | #else /* CONFIG_MMU */ | 192 | #else /* CONFIG_MMU */ |
168 | 193 | ||
169 | /* | 194 | /* |
170 | * Address is valid if: | ||
171 | * - "addr", "addr + size" and "size" are all below the limit | ||
172 | */ | ||
173 | #define access_ok(type, addr, size) \ | ||
174 | (get_fs().seg > (((unsigned long)(addr)) | \ | ||
175 | (size) | ((unsigned long)(addr) + (size)))) | ||
176 | |||
177 | /* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n", | ||
178 | type?"WRITE":"READ",addr,size,get_fs().seg)) */ | ||
179 | |||
180 | /* | ||
181 | * All the __XXX versions macros/functions below do not perform | 195 | * All the __XXX versions macros/functions below do not perform |
182 | * access checking. It is assumed that the necessary checks have been | 196 | * access checking. It is assumed that the necessary checks have been |
183 | * already performed before the finction (macro) is called. | 197 | * already performed before the finction (macro) is called. |
@@ -297,27 +311,34 @@ __asm__ __volatile__ (" lwi %0, %1, 0; \ | |||
297 | ); \ | 311 | ); \ |
298 | }) | 312 | }) |
299 | 313 | ||
300 | /* | 314 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ |
301 | * Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. | 315 | static inline unsigned long __must_check __clear_user(void __user *to, |
302 | */ | 316 | unsigned long n) |
303 | static inline int clear_user(char *to, int size) | ||
304 | { | 317 | { |
305 | if (size && access_ok(VERIFY_WRITE, to, size)) { | 318 | /* normal memset with two words to __ex_table */ |
306 | __asm__ __volatile__ (" \ | 319 | __asm__ __volatile__ ( \ |
307 | 1: \ | 320 | "1: sb r0, %2, r0;" \ |
308 | sb r0, %2, r0; \ | 321 | " addik %0, %0, -1;" \ |
309 | addik %0, %0, -1; \ | 322 | " bneid %0, 1b;" \ |
310 | bneid %0, 1b; \ | 323 | " addik %2, %2, 1;" \ |
311 | addik %2, %2, 1; \ | 324 | "2: " \ |
312 | 2: \ | 325 | __EX_TABLE_SECTION \ |
313 | .section __ex_table,\"a\"; \ | 326 | ".word 1b,2b;" \ |
314 | .word 1b,2b; \ | 327 | ".previous;" \ |
315 | .section .text;" \ | 328 | : "=r"(n) \ |
316 | : "=r"(size) \ | 329 | : "0"(n), "r"(to) |
317 | : "0"(size), "r"(to) | 330 | ); |
318 | ); | 331 | return n; |
319 | } | 332 | } |
320 | return size; | 333 | |
334 | static inline unsigned long __must_check clear_user(void __user *to, | ||
335 | unsigned long n) | ||
336 | { | ||
337 | might_sleep(); | ||
338 | if (unlikely(!access_ok(VERIFY_WRITE, to, n))) | ||
339 | return n; | ||
340 | |||
341 | return __clear_user(to, n); | ||
321 | } | 342 | } |
322 | 343 | ||
323 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) | 344 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) |