diff options
| author | Michal Simek <monstr@monstr.eu> | 2010-03-22 10:46:56 -0400 |
|---|---|---|
| committer | Michal Simek <monstr@monstr.eu> | 2010-04-01 02:38:20 -0400 |
| commit | 0dcb409de73edeb221aed38d9ff8640cf41ff0de (patch) | |
| tree | d58a50ff8fe3e17b43c3db60cb02c6b71d2672ed /arch/microblaze/include | |
| parent | 8b651aa4a7c047b848f3a7bdf0aba9449e6dc3d3 (diff) | |
microblaze: uaccess: sync put/get/clear_user macros
Add macro description and resort.
Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze/include')
| -rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 1e8fa4b76115..6bb9b8fb6655 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
| @@ -191,11 +191,38 @@ extern long strnlen_user(const char *src, long count); | |||
| 191 | 191 | ||
| 192 | #else /* CONFIG_MMU */ | 192 | #else /* CONFIG_MMU */ |
| 193 | 193 | ||
| 194 | /* | 194 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ |
| 195 | * All the __XXX versions macros/functions below do not perform | 195 | static inline unsigned long __must_check __clear_user(void __user *to, |
| 196 | * access checking. It is assumed that the necessary checks have been | 196 | unsigned long n) |
| 197 | * already performed before the finction (macro) is called. | 197 | { |
| 198 | */ | 198 | /* normal memset with two words to __ex_table */ |
| 199 | __asm__ __volatile__ ( \ | ||
| 200 | "1: sb r0, %2, r0;" \ | ||
| 201 | " addik %0, %0, -1;" \ | ||
| 202 | " bneid %0, 1b;" \ | ||
| 203 | " addik %2, %2, 1;" \ | ||
| 204 | "2: " \ | ||
| 205 | __EX_TABLE_SECTION \ | ||
| 206 | ".word 1b,2b;" \ | ||
| 207 | ".previous;" \ | ||
| 208 | : "=r"(n) \ | ||
| 209 | : "0"(n), "r"(to) | ||
| 210 | ); | ||
| 211 | return n; | ||
| 212 | } | ||
| 213 | |||
| 214 | static inline unsigned long __must_check clear_user(void __user *to, | ||
| 215 | unsigned long n) | ||
| 216 | { | ||
| 217 | might_sleep(); | ||
| 218 | if (unlikely(!access_ok(VERIFY_WRITE, to, n))) | ||
| 219 | return n; | ||
| 220 | return __clear_user(to, n); | ||
| 221 | } | ||
| 222 | |||
| 223 | /* put_user and get_user macros */ | ||
| 224 | |||
| 225 | extern long __user_bad(void); | ||
| 199 | 226 | ||
| 200 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | 227 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ |
| 201 | ({ \ | 228 | ({ \ |
| @@ -231,18 +258,53 @@ extern long strnlen_user(const char *src, long count); | |||
| 231 | __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ | 258 | __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ |
| 232 | break; \ | 259 | break; \ |
| 233 | default: \ | 260 | default: \ |
| 234 | __gu_val = 0; __gu_err = -EINVAL; \ | 261 | /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ |
| 235 | } \ | 262 | } \ |
| 236 | x = (__typeof__(*(ptr))) __gu_val; \ | 263 | x = (__typeof__(*(ptr))) __gu_val; \ |
| 237 | __gu_err; \ | 264 | __gu_err; \ |
| 238 | }) | 265 | }) |
| 239 | 266 | ||
| 267 | /** | ||
| 268 | * get_user: - Get a simple variable from user space. | ||
| 269 | * @x: Variable to store result. | ||
| 270 | * @ptr: Source address, in user space. | ||
| 271 | * | ||
| 272 | * Context: User context only. This function may sleep. | ||
| 273 | * | ||
| 274 | * This macro copies a single simple variable from user space to kernel | ||
| 275 | * space. It supports simple types like char and int, but not larger | ||
| 276 | * data types like structures or arrays. | ||
| 277 | * | ||
| 278 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
| 279 | * dereferencing @ptr must be assignable to @x without a cast. | ||
| 280 | * | ||
| 281 | * Returns zero on success, or -EFAULT on error. | ||
| 282 | * On error, the variable @x is set to zero. | ||
| 283 | */ | ||
| 284 | |||
| 240 | #define get_user(x, ptr) \ | 285 | #define get_user(x, ptr) \ |
| 241 | ({ \ | 286 | ({ \ |
| 242 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ | 287 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ |
| 243 | ? __get_user((x), (ptr)) : -EFAULT; \ | 288 | ? __get_user((x), (ptr)) : -EFAULT; \ |
| 244 | }) | 289 | }) |
| 245 | 290 | ||
| 291 | /** | ||
| 292 | * put_user: - Write a simple value into user space. | ||
| 293 | * @x: Value to copy to user space. | ||
| 294 | * @ptr: Destination address, in user space. | ||
| 295 | * | ||
| 296 | * Context: User context only. This function may sleep. | ||
| 297 | * | ||
| 298 | * This macro copies a single simple value from kernel space to user | ||
| 299 | * space. It supports simple types like char and int, but not larger | ||
| 300 | * data types like structures or arrays. | ||
| 301 | * | ||
| 302 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
| 303 | * to the result of dereferencing @ptr. | ||
| 304 | * | ||
| 305 | * Returns zero on success, or -EFAULT on error. | ||
| 306 | */ | ||
| 307 | |||
| 246 | #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | 308 | #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ |
| 247 | ({ \ | 309 | ({ \ |
| 248 | __asm__ __volatile__ ( \ | 310 | __asm__ __volatile__ ( \ |
| @@ -299,7 +361,7 @@ extern long strnlen_user(const char *src, long count); | |||
| 299 | __put_user_asm_8((ptr), __gu_val, __gu_err); \ | 361 | __put_user_asm_8((ptr), __gu_val, __gu_err); \ |
| 300 | break; \ | 362 | break; \ |
| 301 | default: \ | 363 | default: \ |
| 302 | __gu_err = -EINVAL; \ | 364 | /*__gu_err = -EINVAL;*/ __gu_err = __user_bad(); \ |
| 303 | } \ | 365 | } \ |
| 304 | __gu_err; \ | 366 | __gu_err; \ |
| 305 | }) | 367 | }) |
| @@ -310,36 +372,6 @@ extern long strnlen_user(const char *src, long count); | |||
| 310 | ? __put_user((x), (ptr)) : -EFAULT; \ | 372 | ? __put_user((x), (ptr)) : -EFAULT; \ |
| 311 | }) | 373 | }) |
| 312 | 374 | ||
| 313 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ | ||
| 314 | static inline unsigned long __must_check __clear_user(void __user *to, | ||
| 315 | unsigned long n) | ||
| 316 | { | ||
| 317 | /* normal memset with two words to __ex_table */ | ||
| 318 | __asm__ __volatile__ ( \ | ||
| 319 | "1: sb r0, %2, r0;" \ | ||
| 320 | " addik %0, %0, -1;" \ | ||
| 321 | " bneid %0, 1b;" \ | ||
| 322 | " addik %2, %2, 1;" \ | ||
| 323 | "2: " \ | ||
| 324 | __EX_TABLE_SECTION \ | ||
| 325 | ".word 1b,2b;" \ | ||
| 326 | ".previous;" \ | ||
| 327 | : "=r"(n) \ | ||
| 328 | : "0"(n), "r"(to) | ||
| 329 | ); | ||
| 330 | return n; | ||
| 331 | } | ||
| 332 | |||
| 333 | static inline unsigned long __must_check clear_user(void __user *to, | ||
| 334 | unsigned long n) | ||
| 335 | { | ||
| 336 | might_sleep(); | ||
| 337 | if (unlikely(!access_ok(VERIFY_WRITE, to, n))) | ||
| 338 | return n; | ||
| 339 | |||
| 340 | return __clear_user(to, n); | ||
| 341 | } | ||
| 342 | |||
| 343 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) | 375 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) |
| 344 | #define __copy_from_user_inatomic(to, from, n) \ | 376 | #define __copy_from_user_inatomic(to, from, n) \ |
| 345 | copy_from_user((to), (from), (n)) | 377 | copy_from_user((to), (from), (n)) |
