usercopy.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* MN10300 Userspace accessor functions
  2. *
  3. * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
  4. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public Licence
  9. * as published by the Free Software Foundation; either version
  10. * 2 of the Licence, or (at your option) any later version.
  11. */
  12. #include <linux/uaccess.h>
  13. unsigned long
  14. __generic_copy_to_user(void *to, const void *from, unsigned long n)
  15. {
  16. if (access_ok(VERIFY_WRITE, to, n))
  17. __copy_user(to, from, n);
  18. return n;
  19. }
  20. unsigned long
  21. __generic_copy_from_user(void *to, const void *from, unsigned long n)
  22. {
  23. if (access_ok(VERIFY_READ, from, n))
  24. __copy_user_zeroing(to, from, n);
  25. else
  26. memset(to, 0, n);
  27. return n;
  28. }
  29. /*
  30. * Copy a null terminated string from userspace.
  31. */
  32. #define __do_strncpy_from_user(dst, src, count, res) \
  33. do { \
  34. int w; \
  35. asm volatile( \
  36. " mov %1,%0\n" \
  37. " cmp 0,%1\n" \
  38. " beq 2f\n" \
  39. "0:\n" \
  40. " movbu (%5),%2\n" \
  41. "1:\n" \
  42. " movbu %2,(%6)\n" \
  43. " inc %5\n" \
  44. " inc %6\n" \
  45. " cmp 0,%2\n" \
  46. " beq 2f\n" \
  47. " add -1,%1\n" \
  48. " bne 0b\n" \
  49. "2:\n" \
  50. " sub %1,%0\n" \
  51. "3:\n" \
  52. " .section .fixup,\"ax\"\n" \
  53. "4:\n" \
  54. " mov %3,%0\n" \
  55. " jmp 3b\n" \
  56. " .previous\n" \
  57. " .section __ex_table,\"a\"\n" \
  58. " .balign 4\n" \
  59. " .long 0b,4b\n" \
  60. " .long 1b,4b\n" \
  61. " .previous" \
  62. :"=&r"(res), "=r"(count), "=&r"(w) \
  63. :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
  64. : "memory", "cc"); \
  65. } while (0)
  66. long
  67. __strncpy_from_user(char *dst, const char *src, long count)
  68. {
  69. long res;
  70. __do_strncpy_from_user(dst, src, count, res);
  71. return res;
  72. }
  73. long
  74. strncpy_from_user(char *dst, const char *src, long count)
  75. {
  76. long res = -EFAULT;
  77. if (access_ok(VERIFY_READ, src, 1))
  78. __do_strncpy_from_user(dst, src, count, res);
  79. return res;
  80. }
  81. /*
  82. * Clear a userspace memory
  83. */
  84. #define __do_clear_user(addr, size) \
  85. do { \
  86. int w; \
  87. asm volatile( \
  88. " cmp 0,%0\n" \
  89. " beq 1f\n" \
  90. " clr %1\n" \
  91. "0: movbu %1,(%3,%2)\n" \
  92. " inc %3\n" \
  93. " cmp %0,%3\n" \
  94. " bne 0b\n" \
  95. "1:\n" \
  96. " sub %3,%0\n" \
  97. "2:\n" \
  98. ".section .fixup,\"ax\"\n" \
  99. "3: jmp 2b\n" \
  100. ".previous\n" \
  101. ".section __ex_table,\"a\"\n" \
  102. " .balign 4\n" \
  103. " .long 0b,3b\n" \
  104. ".previous\n" \
  105. : "+r"(size), "=&r"(w) \
  106. : "a"(addr), "d"(0) \
  107. : "memory", "cc"); \
  108. } while (0)
  109. unsigned long
  110. __clear_user(void *to, unsigned long n)
  111. {
  112. __do_clear_user(to, n);
  113. return n;
  114. }
  115. unsigned long
  116. clear_user(void *to, unsigned long n)
  117. {
  118. if (access_ok(VERIFY_WRITE, to, n))
  119. __do_clear_user(to, n);
  120. return n;
  121. }
  122. /*
  123. * Return the size of a string (including the ending 0)
  124. *
  125. * Return 0 on exception, a value greater than N if too long
  126. */
  127. long strnlen_user(const char *s, long n)
  128. {
  129. unsigned long res, w;
  130. if (!__addr_ok(s))
  131. return 0;
  132. if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
  133. n = current_thread_info()->addr_limit.seg - (u_long)s;
  134. asm volatile(
  135. "0: cmp %4,%0\n"
  136. " beq 2f\n"
  137. "1: movbu (%0,%3),%1\n"
  138. " inc %0\n"
  139. " cmp 0,%1\n"
  140. " beq 3f\n"
  141. " bra 0b\n"
  142. "2: clr %0\n"
  143. "3:\n"
  144. ".section .fixup,\"ax\"\n"
  145. "4: jmp 2b\n"
  146. ".previous\n"
  147. ".section __ex_table,\"a\"\n"
  148. " .balign 4\n"
  149. " .long 1b,4b\n"
  150. ".previous\n"
  151. :"=d"(res), "=&r"(w)
  152. :"0"(0), "a"(s), "r"(n)
  153. : "memory", "cc");
  154. return res;
  155. }