uaccess.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2009, Wind River Systems Inc
  7. * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
  8. */
  9. #include <linux/export.h>
  10. #include <linux/uaccess.h>
  11. asm(".global __copy_from_user\n"
  12. " .type __copy_from_user, @function\n"
  13. "__copy_from_user:\n"
  14. " movi r2,7\n"
  15. " mov r3,r4\n"
  16. " bge r2,r6,1f\n"
  17. " xor r2,r4,r5\n"
  18. " andi r2,r2,3\n"
  19. " movi r7,3\n"
  20. " beq r2,zero,4f\n"
  21. "1: addi r6,r6,-1\n"
  22. " movi r2,-1\n"
  23. " beq r6,r2,3f\n"
  24. " mov r7,r2\n"
  25. "2: ldbu r2,0(r5)\n"
  26. " addi r6,r6,-1\n"
  27. " addi r5,r5,1\n"
  28. " stb r2,0(r3)\n"
  29. " addi r3,r3,1\n"
  30. " bne r6,r7,2b\n"
  31. "3:\n"
  32. " addi r2,r6,1\n"
  33. " ret\n"
  34. "13:mov r2,r6\n"
  35. " ret\n"
  36. "4: andi r2,r4,1\n"
  37. " cmpeq r2,r2,zero\n"
  38. " beq r2,zero,7f\n"
  39. "5: andi r2,r3,2\n"
  40. " beq r2,zero,6f\n"
  41. "9: ldhu r2,0(r5)\n"
  42. " addi r6,r6,-2\n"
  43. " addi r5,r5,2\n"
  44. " sth r2,0(r3)\n"
  45. " addi r3,r3,2\n"
  46. "6: bge r7,r6,1b\n"
  47. "10:ldw r2,0(r5)\n"
  48. " addi r6,r6,-4\n"
  49. " addi r5,r5,4\n"
  50. " stw r2,0(r3)\n"
  51. " addi r3,r3,4\n"
  52. " br 6b\n"
  53. "7: ldbu r2,0(r5)\n"
  54. " addi r6,r6,-1\n"
  55. " addi r5,r5,1\n"
  56. " addi r3,r4,1\n"
  57. " stb r2,0(r4)\n"
  58. " br 5b\n"
  59. ".section __ex_table,\"a\"\n"
  60. ".word 2b,3b\n"
  61. ".word 9b,13b\n"
  62. ".word 10b,13b\n"
  63. ".word 7b,13b\n"
  64. ".previous\n"
  65. );
  66. EXPORT_SYMBOL(__copy_from_user);
  67. asm(
  68. " .global __copy_to_user\n"
  69. " .type __copy_to_user, @function\n"
  70. "__copy_to_user:\n"
  71. " movi r2,7\n"
  72. " mov r3,r4\n"
  73. " bge r2,r6,1f\n"
  74. " xor r2,r4,r5\n"
  75. " andi r2,r2,3\n"
  76. " movi r7,3\n"
  77. " beq r2,zero,4f\n"
  78. /* Bail if we try to copy zero bytes */
  79. "1: addi r6,r6,-1\n"
  80. " movi r2,-1\n"
  81. " beq r6,r2,3f\n"
  82. /* Copy byte by byte for small copies and if src^dst != 0 */
  83. " mov r7,r2\n"
  84. "2: ldbu r2,0(r5)\n"
  85. " addi r5,r5,1\n"
  86. "9: stb r2,0(r3)\n"
  87. " addi r6,r6,-1\n"
  88. " addi r3,r3,1\n"
  89. " bne r6,r7,2b\n"
  90. "3: addi r2,r6,1\n"
  91. " ret\n"
  92. "13:mov r2,r6\n"
  93. " ret\n"
  94. /* If 'to' is an odd address byte copy */
  95. "4: andi r2,r4,1\n"
  96. " cmpeq r2,r2,zero\n"
  97. " beq r2,zero,7f\n"
  98. /* If 'to' is not divideable by four copy halfwords */
  99. "5: andi r2,r3,2\n"
  100. " beq r2,zero,6f\n"
  101. " ldhu r2,0(r5)\n"
  102. " addi r5,r5,2\n"
  103. "10:sth r2,0(r3)\n"
  104. " addi r6,r6,-2\n"
  105. " addi r3,r3,2\n"
  106. /* Copy words */
  107. "6: bge r7,r6,1b\n"
  108. " ldw r2,0(r5)\n"
  109. " addi r5,r5,4\n"
  110. "11:stw r2,0(r3)\n"
  111. " addi r6,r6,-4\n"
  112. " addi r3,r3,4\n"
  113. " br 6b\n"
  114. /* Copy remaining bytes */
  115. "7: ldbu r2,0(r5)\n"
  116. " addi r5,r5,1\n"
  117. " addi r3,r4,1\n"
  118. "12: stb r2,0(r4)\n"
  119. " addi r6,r6,-1\n"
  120. " br 5b\n"
  121. ".section __ex_table,\"a\"\n"
  122. ".word 9b,3b\n"
  123. ".word 10b,13b\n"
  124. ".word 11b,13b\n"
  125. ".word 12b,13b\n"
  126. ".previous\n");
  127. EXPORT_SYMBOL(__copy_to_user);
  128. long strncpy_from_user(char *__to, const char __user *__from, long __len)
  129. {
  130. int l = strnlen_user(__from, __len);
  131. int is_zt = 1;
  132. if (l > __len) {
  133. is_zt = 0;
  134. l = __len;
  135. }
  136. if (l == 0 || copy_from_user(__to, __from, l))
  137. return -EFAULT;
  138. if (is_zt)
  139. l--;
  140. return l;
  141. }
  142. long strnlen_user(const char __user *s, long n)
  143. {
  144. long i;
  145. for (i = 0; i < n; i++) {
  146. char c;
  147. if (get_user(c, s + i) == -EFAULT)
  148. return 0;
  149. if (c == 0)
  150. return i + 1;
  151. }
  152. return n + 1;
  153. }