uaccess-kernel.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * linux/arch/arm26/lib/uaccess-kernel.S
  3. *
  4. * Copyright (C) 1998 Russell King
  5. *
  6. * Note! Some code fragments found in here have a special calling
  7. * convention - they are not APCS compliant!
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/linkage.h>
  14. #include <asm/assembler.h>
  15. .text
  16. //FIXME - surely this can be done in C not asm, removing the problem of keeping C and asm in sync? (this is a struct uaccess_t)
  17. .globl uaccess_kernel
  18. uaccess_kernel:
  19. .word uaccess_kernel_put_byte
  20. .word uaccess_kernel_get_byte
  21. .word uaccess_kernel_put_half
  22. .word uaccess_kernel_get_half
  23. .word uaccess_kernel_put_word
  24. .word uaccess_kernel_get_word
  25. .word uaccess_kernel_put_dword
  26. .word uaccess_kernel_copy
  27. .word uaccess_kernel_copy
  28. .word uaccess_kernel_clear
  29. .word uaccess_kernel_strncpy
  30. .word uaccess_kernel_strnlen
  31. @ In : r0 = x, r1 = addr, r2 = error
  32. @ Out: r2 = error
  33. uaccess_kernel_put_byte:
  34. stmfd sp!, {lr}
  35. strb r0, [r1]
  36. ldmfd sp!, {pc}^
  37. @ In : r0 = x, r1 = addr, r2 = error
  38. @ Out: r2 = error
  39. uaccess_kernel_put_half:
  40. stmfd sp!, {lr}
  41. strb r0, [r1]
  42. mov r0, r0, lsr #8
  43. strb r0, [r1, #1]
  44. ldmfd sp!, {pc}^
  45. @ In : r0 = x, r1 = addr, r2 = error
  46. @ Out: r2 = error
  47. uaccess_kernel_put_word:
  48. stmfd sp!, {lr}
  49. str r0, [r1]
  50. ldmfd sp!, {pc}^
  51. @ In : r0 = x, r1 = addr, r2 = error
  52. @ Out: r2 = error
  53. uaccess_kernel_put_dword:
  54. stmfd sp!, {lr}
  55. str r0, [r1], #4
  56. str r0, [r1], #0
  57. ldmfd sp!, {pc}^
  58. @ In : r0 = addr, r1 = error
  59. @ Out: r0 = x, r1 = error
  60. uaccess_kernel_get_byte:
  61. stmfd sp!, {lr}
  62. ldrb r0, [r0]
  63. ldmfd sp!, {pc}^
  64. @ In : r0 = addr, r1 = error
  65. @ Out: r0 = x, r1 = error
  66. uaccess_kernel_get_half:
  67. stmfd sp!, {lr}
  68. ldr r0, [r0]
  69. mov r0, r0, lsl #16
  70. mov r0, r0, lsr #16
  71. ldmfd sp!, {pc}^
  72. @ In : r0 = addr, r1 = error
  73. @ Out: r0 = x, r1 = error
  74. uaccess_kernel_get_word:
  75. stmfd sp!, {lr}
  76. ldr r0, [r0]
  77. ldmfd sp!, {pc}^
  78. /* Prototype: int uaccess_kernel_copy(void *to, const char *from, size_t n)
  79. * Purpose : copy a block to kernel memory from kernel memory
  80. * Params : to - kernel memory
  81. * : from - kernel memory
  82. * : n - number of bytes to copy
  83. * Returns : Number of bytes NOT copied.
  84. */
  85. uaccess_kernel_copy:
  86. stmfd sp!, {lr}
  87. bl memcpy
  88. mov r0, #0
  89. ldmfd sp!, {pc}^
  90. /* Prototype: int uaccess_kernel_clear(void *addr, size_t sz)
  91. * Purpose : clear some kernel memory
  92. * Params : addr - kernel memory address to clear
  93. * : sz - number of bytes to clear
  94. * Returns : number of bytes NOT cleared
  95. */
  96. uaccess_kernel_clear:
  97. stmfd sp!, {lr}
  98. mov r2, #0
  99. cmp r1, #4
  100. blt 2f
  101. ands ip, r0, #3
  102. beq 1f
  103. cmp ip, #1
  104. strb r2, [r0], #1
  105. strleb r2, [r0], #1
  106. strltb r2, [r0], #1
  107. rsb ip, ip, #4
  108. sub r1, r1, ip @ 7 6 5 4 3 2 1
  109. 1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
  110. bmi 2f
  111. str r2, [r0], #4
  112. str r2, [r0], #4
  113. b 1b
  114. 2: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
  115. strpl r2, [r0], #4
  116. tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
  117. strneb r2, [r0], #1
  118. strneb r2, [r0], #1
  119. tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
  120. strneb r2, [r0], #1
  121. mov r0, #0
  122. ldmfd sp!, {pc}^
  123. /* Prototype: size_t uaccess_kernel_strncpy(char *dst, char *src, size_t len)
  124. * Purpose : copy a string from kernel memory to kernel memory
  125. * Params : dst - kernel memory destination
  126. * : src - kernel memory source
  127. * : len - maximum length of string
  128. * Returns : number of characters copied
  129. */
  130. uaccess_kernel_strncpy:
  131. stmfd sp!, {lr}
  132. mov ip, r2
  133. 1: subs r2, r2, #1
  134. bmi 2f
  135. ldrb r3, [r1], #1
  136. strb r3, [r0], #1
  137. teq r3, #0
  138. bne 1b
  139. 2: subs r0, ip, r2
  140. ldmfd sp!, {pc}^
  141. /* Prototype: int uaccess_kernel_strlen(char *str, long n)
  142. * Purpose : get length of a string in kernel memory
  143. * Params : str - address of string in kernel memory
  144. * Returns : length of string *including terminator*,
  145. * or zero on exception, or n + 1 if too long
  146. */
  147. uaccess_kernel_strnlen:
  148. stmfd sp!, {lr}
  149. mov r2, r0
  150. 1: ldrb r1, [r0], #1
  151. teq r1, #0
  152. beq 2f
  153. subs r1, r1, #1
  154. bne 1b
  155. add r0, r0, #1
  156. 2: sub r0, r0, r2
  157. ldmfd sp!, {pc}^