uaccess_old.S 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
  3. * Copyright (C) 2009 PetaLogix
  4. * Copyright (C) 2007 LynuxWorks, Inc.
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. */
  10. #include <linux/errno.h>
  11. #include <linux/linkage.h>
  12. #include <asm/page.h>
  13. /*
  14. * int __strncpy_user(char *to, char *from, int len);
  15. *
  16. * Returns:
  17. * -EFAULT for an exception
  18. * len if we hit the buffer limit
  19. * bytes copied
  20. */
  21. .text
  22. .globl __strncpy_user;
  23. .type __strncpy_user, @function
  24. .align 4;
  25. __strncpy_user:
  26. /*
  27. * r5 - to
  28. * r6 - from
  29. * r7 - len
  30. * r3 - temp count
  31. * r4 - temp val
  32. */
  33. beqid r7,3f
  34. addik r3,r7,0 /* temp_count = len */
  35. 1:
  36. lbu r4,r6,r0
  37. beqid r4,2f
  38. sb r4,r5,r0
  39. addik r5,r5,1
  40. addik r6,r6,1 /* delay slot */
  41. addik r3,r3,-1
  42. bnei r3,1b /* break on len */
  43. 2:
  44. rsubk r3,r3,r7 /* temp_count = len - temp_count */
  45. 3:
  46. rtsd r15,8
  47. nop
  48. .size __strncpy_user, . - __strncpy_user
  49. .section .fixup, "ax"
  50. .align 2
  51. 4:
  52. brid 3b
  53. addik r3,r0, -EFAULT
  54. .section __ex_table, "a"
  55. .word 1b,4b
  56. /*
  57. * int __strnlen_user(char __user *str, int maxlen);
  58. *
  59. * Returns:
  60. * 0 on error
  61. * maxlen + 1 if no NUL byte found within maxlen bytes
  62. * size of the string (including NUL byte)
  63. */
  64. .text
  65. .globl __strnlen_user;
  66. .type __strnlen_user, @function
  67. .align 4;
  68. __strnlen_user:
  69. beqid r6,3f
  70. addik r3,r6,0
  71. 1:
  72. lbu r4,r5,r0
  73. beqid r4,2f /* break on NUL */
  74. addik r3,r3,-1 /* delay slot */
  75. bneid r3,1b
  76. addik r5,r5,1 /* delay slot */
  77. addik r3,r3,-1 /* for break on len */
  78. 2:
  79. rsubk r3,r3,r6
  80. 3:
  81. rtsd r15,8
  82. nop
  83. .size __strnlen_user, . - __strnlen_user
  84. .section .fixup,"ax"
  85. 4:
  86. brid 3b
  87. addk r3,r0,r0
  88. .section __ex_table,"a"
  89. .word 1b,4b
  90. /* Loop unrolling for __copy_tofrom_user */
  91. #define COPY(offset) \
  92. 1: lwi r4 , r6, 0x0000 + offset; \
  93. 2: lwi r19, r6, 0x0004 + offset; \
  94. 3: lwi r20, r6, 0x0008 + offset; \
  95. 4: lwi r21, r6, 0x000C + offset; \
  96. 5: lwi r22, r6, 0x0010 + offset; \
  97. 6: lwi r23, r6, 0x0014 + offset; \
  98. 7: lwi r24, r6, 0x0018 + offset; \
  99. 8: lwi r25, r6, 0x001C + offset; \
  100. 9: swi r4 , r5, 0x0000 + offset; \
  101. 10: swi r19, r5, 0x0004 + offset; \
  102. 11: swi r20, r5, 0x0008 + offset; \
  103. 12: swi r21, r5, 0x000C + offset; \
  104. 13: swi r22, r5, 0x0010 + offset; \
  105. 14: swi r23, r5, 0x0014 + offset; \
  106. 15: swi r24, r5, 0x0018 + offset; \
  107. 16: swi r25, r5, 0x001C + offset; \
  108. .section __ex_table,"a"; \
  109. .word 1b, 33f; \
  110. .word 2b, 33f; \
  111. .word 3b, 33f; \
  112. .word 4b, 33f; \
  113. .word 5b, 33f; \
  114. .word 6b, 33f; \
  115. .word 7b, 33f; \
  116. .word 8b, 33f; \
  117. .word 9b, 33f; \
  118. .word 10b, 33f; \
  119. .word 11b, 33f; \
  120. .word 12b, 33f; \
  121. .word 13b, 33f; \
  122. .word 14b, 33f; \
  123. .word 15b, 33f; \
  124. .word 16b, 33f; \
  125. .text
  126. #define COPY_80(offset) \
  127. COPY(0x00 + offset);\
  128. COPY(0x20 + offset);\
  129. COPY(0x40 + offset);\
  130. COPY(0x60 + offset);
  131. /*
  132. * int __copy_tofrom_user(char *to, char *from, int len)
  133. * Return:
  134. * 0 on success
  135. * number of not copied bytes on error
  136. */
  137. .text
  138. .globl __copy_tofrom_user;
  139. .type __copy_tofrom_user, @function
  140. .align 4;
  141. __copy_tofrom_user:
  142. /*
  143. * r5 - to
  144. * r6 - from
  145. * r7, r3 - count
  146. * r4 - tempval
  147. */
  148. beqid r7, 0f /* zero size is not likely */
  149. or r3, r5, r6 /* find if is any to/from unaligned */
  150. or r3, r3, r7 /* find if count is unaligned */
  151. andi r3, r3, 0x3 /* mask last 3 bits */
  152. bneid r3, bu1 /* if r3 is not zero then byte copying */
  153. or r3, r0, r0
  154. rsubi r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
  155. beqid r3, page;
  156. or r3, r0, r0
  157. w1: lw r4, r6, r3 /* at least one 4 byte copy */
  158. w2: sw r4, r5, r3
  159. addik r7, r7, -4
  160. bneid r7, w1
  161. addik r3, r3, 4
  162. addik r3, r7, 0
  163. rtsd r15, 8
  164. nop
  165. .section __ex_table,"a"
  166. .word w1, 0f;
  167. .word w2, 0f;
  168. .text
  169. .align 4 /* Alignment is important to keep icache happy */
  170. page: /* Create room on stack and save registers for storign values */
  171. addik r1, r1, -40
  172. swi r5, r1, 0
  173. swi r6, r1, 4
  174. swi r7, r1, 8
  175. swi r19, r1, 12
  176. swi r20, r1, 16
  177. swi r21, r1, 20
  178. swi r22, r1, 24
  179. swi r23, r1, 28
  180. swi r24, r1, 32
  181. swi r25, r1, 36
  182. loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
  183. /* Loop unrolling to get performance boost */
  184. COPY_80(0x000);
  185. COPY_80(0x080);
  186. COPY_80(0x100);
  187. COPY_80(0x180);
  188. /* copy loop */
  189. addik r6, r6, 0x200
  190. addik r7, r7, -0x200
  191. bneid r7, loop
  192. addik r5, r5, 0x200
  193. /* Restore register content */
  194. lwi r5, r1, 0
  195. lwi r6, r1, 4
  196. lwi r7, r1, 8
  197. lwi r19, r1, 12
  198. lwi r20, r1, 16
  199. lwi r21, r1, 20
  200. lwi r22, r1, 24
  201. lwi r23, r1, 28
  202. lwi r24, r1, 32
  203. lwi r25, r1, 36
  204. addik r1, r1, 40
  205. /* return back */
  206. addik r3, r0, 0
  207. rtsd r15, 8
  208. nop
  209. /* Fault case - return temp count */
  210. 33:
  211. addik r3, r7, 0
  212. /* Restore register content */
  213. lwi r5, r1, 0
  214. lwi r6, r1, 4
  215. lwi r7, r1, 8
  216. lwi r19, r1, 12
  217. lwi r20, r1, 16
  218. lwi r21, r1, 20
  219. lwi r22, r1, 24
  220. lwi r23, r1, 28
  221. lwi r24, r1, 32
  222. lwi r25, r1, 36
  223. addik r1, r1, 40
  224. /* return back */
  225. rtsd r15, 8
  226. nop
  227. .align 4 /* Alignment is important to keep icache happy */
  228. bu1: lbu r4,r6,r3
  229. bu2: sb r4,r5,r3
  230. addik r7,r7,-1
  231. bneid r7,bu1
  232. addik r3,r3,1 /* delay slot */
  233. 0:
  234. addik r3,r7,0
  235. rtsd r15,8
  236. nop
  237. .size __copy_tofrom_user, . - __copy_tofrom_user
  238. .section __ex_table,"a"
  239. .word bu1, 0b;
  240. .word bu2, 0b;
  241. .text