1/* MN10300 userspace access functions 2 * 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11#ifndef _ASM_UACCESS_H 12#define _ASM_UACCESS_H 13 14/* 15 * User space memory access functions 16 */ 17#include <linux/thread_info.h> 18#include <linux/kernel.h> 19#include <asm/page.h> 20#include <asm/errno.h> 21 22#define VERIFY_READ 0 23#define VERIFY_WRITE 1 24 25/* 26 * The fs value determines whether argument validity checking should be 27 * performed or not. If get_fs() == USER_DS, checking is performed, with 28 * get_fs() == KERNEL_DS, checking is bypassed. 29 * 30 * For historical reasons, these macros are grossly misnamed. 31 */ 32#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 33 34#define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF) 35#define KERNEL_DS MAKE_MM_SEG(0x9FFFFFFF) 36#define USER_DS MAKE_MM_SEG(TASK_SIZE) 37 38#define get_ds() (KERNEL_DS) 39#define get_fs() (current_thread_info()->addr_limit) 40#define set_fs(x) (current_thread_info()->addr_limit = (x)) 41#define __kernel_ds_p() (current_thread_info()->addr_limit.seg == 0x9FFFFFFF) 42 43#define segment_eq(a, b) ((a).seg == (b).seg) 44 45#define __addr_ok(addr) \ 46 ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) 47 48/* 49 * check that a range of addresses falls within the current address limit 50 */ 51static inline int ___range_ok(unsigned long addr, unsigned int size) 52{ 53 int flag = 1, tmp; 54 55 asm(" add %3,%1 \n" /* set C-flag if addr + size > 4Gb */ 56 " bcs 0f \n" 57 " cmp %4,%1 \n" /* jump if addr+size>limit (error) */ 58 " bhi 0f \n" 59 " clr %0 \n" /* mark okay */ 60 "0: \n" 61 : "=r"(flag), "=&r"(tmp) 62 : "1"(addr), "ir"(size), 63 "r"(current_thread_info()->addr_limit.seg), "0"(flag) 64 : "cc" 65 ); 66 67 return flag; 68} 69 70#define __range_ok(addr, size) ___range_ok((unsigned long)(addr), (u32)(size)) 71 72#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0) 73#define __access_ok(addr, size) (__range_ok((addr), (size)) == 0) 74 75static inline int verify_area(int type, const void *addr, unsigned long size) 76{ 77 return access_ok(type, addr, size) ? 0 : -EFAULT; 78} 79 80 81/* 82 * The exception table consists of pairs of addresses: the first is the 83 * address of an instruction that is allowed to fault, and the second is 84 * the address at which the program should continue. No registers are 85 * modified, so it is entirely up to the continuation code to figure out 86 * what to do. 87 * 88 * All the routines below use bits of fixup code that are out of line 89 * with the main instruction path. This means when everything is well, 90 * we don't even have to jump over them. Further, they do not intrude 91 * on our cache or tlb entries. 92 */ 93 94struct exception_table_entry 95{ 96 unsigned long insn, fixup; 97}; 98 99/* Returns 0 if exception not found and fixup otherwise. */ 100extern int fixup_exception(struct pt_regs *regs); 101 102#define put_user(x, ptr) __put_user_check((x), (ptr), sizeof(*(ptr))) 103#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr))) 104 105/* 106 * The "__xxx" versions do not do address space checking, useful when 107 * doing multiple accesses to the same area (the user has to do the 108 * checks by hand with "access_ok()") 109 */ 110#define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr))) 111#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) 112 113/* 114 * The "xxx_ret" versions return constant specified in third argument, if 115 * something bad happens. These macros can be optimized for the 116 * case of just returning from the function xxx_ret is used. 117 */ 118 119#define put_user_ret(x, ptr, ret) \ 120 ({ if (put_user((x), (ptr))) return (ret); }) 121#define get_user_ret(x, ptr, ret) \ 122 ({ if (get_user((x), (ptr))) return (ret); }) 123#define __put_user_ret(x, ptr, ret) \ 124 ({ if (__put_user((x), (ptr))) return (ret); }) 125#define __get_user_ret(x, ptr, ret) \ 126 ({ if (__get_user((x), (ptr))) return (ret); }) 127 128struct __large_struct { unsigned long buf[100]; }; 129#define __m(x) (*(struct __large_struct *)(x)) 130 131#define __get_user_nocheck(x, ptr, size) \ 132({ \ 133 unsigned long __gu_addr; \ 134 int __gu_err; \ 135 __gu_addr = (unsigned long) (ptr); \ 136 switch (size) { \ 137 case 1: { \ 138 unsigned char __gu_val; \ 139 __get_user_asm("bu"); \ 140 (x) = *(__force __typeof__(*(ptr))*) &__gu_val; \ 141 break; \ 142 } \ 143 case 2: { \ 144 unsigned short __gu_val; \ 145 __get_user_asm("hu"); \ 146 (x) = *(__force __typeof__(*(ptr))*) &__gu_val; \ 147 break; \ 148 } \ 149 case 4: { \ 150 unsigned int __gu_val; \ 151 __get_user_asm(""); \ 152 (x) = *(__force __typeof__(*(ptr))*) &__gu_val; \ 153 break; \ 154 } \ 155 default: \ 156 __get_user_unknown(); \ 157 break; \ 158 } \ 159 __gu_err; \ 160}) 161 162#define __get_user_check(x, ptr, size) \ 163({ \ 164 const __typeof__(ptr) __guc_ptr = (ptr); \ 165 int _e; \ 166 if (likely(__access_ok((unsigned long) __guc_ptr, (size)))) \ 167 _e = __get_user_nocheck((x), __guc_ptr, (size)); \ 168 else { \ 169 _e = -EFAULT; \ 170 (x) = (__typeof__(x))0; \ 171 } \ 172 _e; \ 173}) 174 175#define __get_user_asm(INSN) \ 176({ \ 177 asm volatile( \ 178 "1:\n" \ 179 " mov"INSN" %2,%1\n" \ 180 " mov 0,%0\n" \ 181 "2:\n" \ 182 " .section .fixup,\"ax\"\n" \ 183 "3:\n\t" \ 184 " mov %3,%0\n" \ 185 " jmp 2b\n" \ 186 " .previous\n" \ 187 " .section __ex_table,\"a\"\n" \ 188 " .balign 4\n" \ 189 " .long 1b, 3b\n" \ 190 " .previous" \ 191 : "=&r" (__gu_err), "=&r" (__gu_val) \ 192 : "m" (__m(__gu_addr)), "i" (-EFAULT)); \ 193}) 194 195extern int __get_user_unknown(void); 196 197#define __put_user_nocheck(x, ptr, size) \ 198({ \ 199 union { \ 200 __typeof__(*(ptr)) val; \ 201 u32 bits[2]; \ 202 } __pu_val; \ 203 unsigned long __pu_addr; \ 204 int __pu_err; \ 205 __pu_val.val = (x); \ 206 __pu_addr = (unsigned long) (ptr); \ 207 switch (size) { \ 208 case 1: __put_user_asm("bu"); break; \ 209 case 2: __put_user_asm("hu"); break; \ 210 case 4: __put_user_asm("" ); break; \ 211 case 8: __put_user_asm8(); break; \ 212 default: __pu_err = __put_user_unknown(); break; \ 213 } \ 214 __pu_err; \ 215}) 216 217#define __put_user_check(x, ptr, size) \ 218({ \ 219 union { \ 220 __typeof__(*(ptr)) val; \ 221 u32 bits[2]; \ 222 } __pu_val; \ 223 unsigned long __pu_addr; \ 224 int __pu_err; \ 225 __pu_val.val = (x); \ 226 __pu_addr = (unsigned long) (ptr); \ 227 if (likely(__access_ok(__pu_addr, size))) { \ 228 switch (size) { \ 229 case 1: __put_user_asm("bu"); break; \ 230 case 2: __put_user_asm("hu"); break; \ 231 case 4: __put_user_asm("" ); break; \ 232 case 8: __put_user_asm8(); break; \ 233 default: __pu_err = __put_user_unknown(); break; \ 234 } \ 235 } \ 236 else { \ 237 __pu_err = -EFAULT; \ 238 } \ 239 __pu_err; \ 240}) 241 242#define __put_user_asm(INSN) \ 243({ \ 244 asm volatile( \ 245 "1:\n" \ 246 " mov"INSN" %1,%2\n" \ 247 " mov 0,%0\n" \ 248 "2:\n" \ 249 " .section .fixup,\"ax\"\n" \ 250 "3:\n" \ 251 " mov %3,%0\n" \ 252 " jmp 2b\n" \ 253 " .previous\n" \ 254 " .section __ex_table,\"a\"\n" \ 255 " .balign 4\n" \ 256 " .long 1b, 3b\n" \ 257 " .previous" \ 258 : "=&r" (__pu_err) \ 259 : "r" (__pu_val.val), "m" (__m(__pu_addr)), \ 260 "i" (-EFAULT) \ 261 ); \ 262}) 263 264#define __put_user_asm8() \ 265({ \ 266 asm volatile( \ 267 "1: mov %1,%3 \n" \ 268 "2: mov %2,%4 \n" \ 269 " mov 0,%0 \n" \ 270 "3: \n" \ 271 " .section .fixup,\"ax\" \n" \ 272 "4: \n" \ 273 " mov %5,%0 \n" \ 274 " jmp 3b \n" \ 275 " .previous \n" \ 276 " .section __ex_table,\"a\"\n" \ 277 " .balign 4 \n" \ 278 " .long 1b, 4b \n" \ 279 " .long 2b, 4b \n" \ 280 " .previous \n" \ 281 : "=&r" (__pu_err) \ 282 : "r" (__pu_val.bits[0]), "r" (__pu_val.bits[1]), \ 283 "m" (__m(__pu_addr)), "m" (__m(__pu_addr+4)), \ 284 "i" (-EFAULT) \ 285 ); \ 286}) 287 288extern int __put_user_unknown(void); 289 290 291/* 292 * Copy To/From Userspace 293 */ 294/* Generic arbitrary sized copy. */ 295#define __copy_user(to, from, size) \ 296do { \ 297 if (size) { \ 298 void *__to = to; \ 299 const void *__from = from; \ 300 int w; \ 301 asm volatile( \ 302 "0: movbu (%0),%3;\n" \ 303 "1: movbu %3,(%1);\n" \ 304 " inc %0;\n" \ 305 " inc %1;\n" \ 306 " add -1,%2;\n" \ 307 " bne 0b;\n" \ 308 "2:\n" \ 309 " .section .fixup,\"ax\"\n" \ 310 "3: jmp 2b\n" \ 311 " .previous\n" \ 312 " .section __ex_table,\"a\"\n" \ 313 " .balign 4\n" \ 314 " .long 0b,3b\n" \ 315 " .long 1b,3b\n" \ 316 " .previous\n" \ 317 : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\ 318 : "0"(__from), "1"(__to), "2"(size) \ 319 : "cc", "memory"); \ 320 } \ 321} while (0) 322 323#define __copy_user_zeroing(to, from, size) \ 324do { \ 325 if (size) { \ 326 void *__to = to; \ 327 const void *__from = from; \ 328 int w; \ 329 asm volatile( \ 330 "0: movbu (%0),%3;\n" \ 331 "1: movbu %3,(%1);\n" \ 332 " inc %0;\n" \ 333 " inc %1;\n" \ 334 " add -1,%2;\n" \ 335 " bne 0b;\n" \ 336 "2:\n" \ 337 " .section .fixup,\"ax\"\n" \ 338 "3:\n" \ 339 " mov %2,%0\n" \ 340 " clr %3\n" \ 341 "4: movbu %3,(%1);\n" \ 342 " inc %1;\n" \ 343 " add -1,%2;\n" \ 344 " bne 4b;\n" \ 345 " mov %0,%2\n" \ 346 " jmp 2b\n" \ 347 " .previous\n" \ 348 " .section __ex_table,\"a\"\n" \ 349 " .balign 4\n" \ 350 " .long 0b,3b\n" \ 351 " .long 1b,3b\n" \ 352 " .previous\n" \ 353 : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\ 354 : "0"(__from), "1"(__to), "2"(size) \ 355 : "cc", "memory"); \ 356 } \ 357} while (0) 358 359/* We let the __ versions of copy_from/to_user inline, because they're often 360 * used in fast paths and have only a small space overhead. 361 */ 362static inline 363unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, 364 unsigned long n) 365{ 366 __copy_user_zeroing(to, from, n); 367 return n; 368} 369 370static inline 371unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, 372 unsigned long n) 373{ 374 __copy_user(to, from, n); 375 return n; 376} 377 378 379#if 0 380#error "don't use - these macros don't increment to & from pointers" 381/* Optimize just a little bit when we know the size of the move. */ 382#define __constant_copy_user(to, from, size) \ 383do { \ 384 asm volatile( \ 385 " mov %0,a0;\n" \ 386 "0: movbu (%1),d3;\n" \ 387 "1: movbu d3,(%2);\n" \ 388 " add -1,a0;\n" \ 389 " bne 0b;\n" \ 390 "2:;" \ 391 ".section .fixup,\"ax\"\n" \ 392 "3: jmp 2b\n" \ 393 ".previous\n" \ 394 ".section __ex_table,\"a\"\n" \ 395 " .balign 4\n" \ 396 " .long 0b,3b\n" \ 397 " .long 1b,3b\n" \ 398 ".previous" \ 399 : \ 400 : "d"(size), "d"(to), "d"(from) \ 401 : "d3", "a0"); \ 402} while (0) 403 404/* Optimize just a little bit when we know the size of the move. */ 405#define __constant_copy_user_zeroing(to, from, size) \ 406do { \ 407 asm volatile( \ 408 " mov %0,a0;\n" \ 409 "0: movbu (%1),d3;\n" \ 410 "1: movbu d3,(%2);\n" \ 411 " add -1,a0;\n" \ 412 " bne 0b;\n" \ 413 "2:;" \ 414 ".section .fixup,\"ax\"\n" \ 415 "3: jmp 2b\n" \ 416 ".previous\n" \ 417 ".section __ex_table,\"a\"\n" \ 418 " .balign 4\n" \ 419 " .long 0b,3b\n" \ 420 " .long 1b,3b\n" \ 421 ".previous" \ 422 : \ 423 : "d"(size), "d"(to), "d"(from) \ 424 : "d3", "a0"); \ 425} while (0) 426 427static inline 428unsigned long __constant_copy_to_user(void *to, const void *from, 429 unsigned long n) 430{ 431 if (access_ok(VERIFY_WRITE, to, n)) 432 __constant_copy_user(to, from, n); 433 return n; 434} 435 436static inline 437unsigned long __constant_copy_from_user(void *to, const void *from, 438 unsigned long n) 439{ 440 if (access_ok(VERIFY_READ, from, n)) 441 __constant_copy_user_zeroing(to, from, n); 442 return n; 443} 444 445static inline 446unsigned long __constant_copy_to_user_nocheck(void *to, const void *from, 447 unsigned long n) 448{ 449 __constant_copy_user(to, from, n); 450 return n; 451} 452 453static inline 454unsigned long __constant_copy_from_user_nocheck(void *to, const void *from, 455 unsigned long n) 456{ 457 __constant_copy_user_zeroing(to, from, n); 458 return n; 459} 460#endif 461 462extern unsigned long __generic_copy_to_user(void __user *, const void *, 463 unsigned long); 464extern unsigned long __generic_copy_from_user(void *, const void __user *, 465 unsigned long); 466 467#define __copy_to_user_inatomic(to, from, n) \ 468 __generic_copy_to_user_nocheck((to), (from), (n)) 469#define __copy_from_user_inatomic(to, from, n) \ 470 __generic_copy_from_user_nocheck((to), (from), (n)) 471 472#define __copy_to_user(to, from, n) \ 473({ \ 474 might_sleep(); \ 475 __copy_to_user_inatomic((to), (from), (n)); \ 476}) 477 478#define __copy_from_user(to, from, n) \ 479({ \ 480 might_sleep(); \ 481 __copy_from_user_inatomic((to), (from), (n)); \ 482}) 483 484 485#define copy_to_user(to, from, n) __generic_copy_to_user((to), (from), (n)) 486#define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n)) 487 488extern long strncpy_from_user(char *dst, const char __user *src, long count); 489extern long __strncpy_from_user(char *dst, const char __user *src, long count); 490extern long strnlen_user(const char __user *str, long n); 491#define strlen_user(str) strnlen_user(str, ~0UL >> 1) 492extern unsigned long clear_user(void __user *mem, unsigned long len); 493extern unsigned long __clear_user(void __user *mem, unsigned long len); 494 495#endif /* _ASM_UACCESS_H */ 496