copy_user.S 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * arch/alpha/lib/copy_user.S
  3. *
  4. * Copy to/from user space, handling exceptions as we go.. This
  5. * isn't exactly pretty.
  6. *
  7. * This is essentially the same as "memcpy()", but with a few twists.
  8. * Notably, we have to make sure that $0 is always up-to-date and
  9. * contains the right "bytes left to copy" value (and that it is updated
  10. * only _after_ a successful copy). There is also some rather minor
  11. * exception setup stuff..
  12. *
  13. * NOTE! This is not directly C-callable, because the calling semantics are
  14. * different:
  15. *
  16. * Inputs:
  17. * length in $0
  18. * destination address in $6
  19. * source address in $7
  20. * return address in $28
  21. *
  22. * Outputs:
  23. * bytes left to copy in $0
  24. *
  25. * Clobbers:
  26. * $1,$2,$3,$4,$5,$6,$7
  27. */
  28. /* Allow an exception for an insn; exit if we get one. */
  29. #define EXI(x,y...) \
  30. 99: x,##y; \
  31. .section __ex_table,"a"; \
  32. .long 99b - .; \
  33. lda $31, $exitin-99b($31); \
  34. .previous
  35. #define EXO(x,y...) \
  36. 99: x,##y; \
  37. .section __ex_table,"a"; \
  38. .long 99b - .; \
  39. lda $31, $exitout-99b($31); \
  40. .previous
  41. .set noat
  42. .align 4
  43. .globl __copy_user
  44. .ent __copy_user
  45. __copy_user:
  46. .prologue 0
  47. and $6,7,$3
  48. beq $0,$35
  49. beq $3,$36
  50. subq $3,8,$3
  51. .align 4
  52. $37:
  53. EXI( ldq_u $1,0($7) )
  54. EXO( ldq_u $2,0($6) )
  55. extbl $1,$7,$1
  56. mskbl $2,$6,$2
  57. insbl $1,$6,$1
  58. addq $3,1,$3
  59. bis $1,$2,$1
  60. EXO( stq_u $1,0($6) )
  61. subq $0,1,$0
  62. addq $6,1,$6
  63. addq $7,1,$7
  64. beq $0,$41
  65. bne $3,$37
  66. $36:
  67. and $7,7,$1
  68. bic $0,7,$4
  69. beq $1,$43
  70. beq $4,$48
  71. EXI( ldq_u $3,0($7) )
  72. .align 4
  73. $50:
  74. EXI( ldq_u $2,8($7) )
  75. subq $4,8,$4
  76. extql $3,$7,$3
  77. extqh $2,$7,$1
  78. bis $3,$1,$1
  79. EXO( stq $1,0($6) )
  80. addq $7,8,$7
  81. subq $0,8,$0
  82. addq $6,8,$6
  83. bis $2,$2,$3
  84. bne $4,$50
  85. $48:
  86. beq $0,$41
  87. .align 4
  88. $57:
  89. EXI( ldq_u $1,0($7) )
  90. EXO( ldq_u $2,0($6) )
  91. extbl $1,$7,$1
  92. mskbl $2,$6,$2
  93. insbl $1,$6,$1
  94. bis $1,$2,$1
  95. EXO( stq_u $1,0($6) )
  96. subq $0,1,$0
  97. addq $6,1,$6
  98. addq $7,1,$7
  99. bne $0,$57
  100. br $31,$41
  101. .align 4
  102. $43:
  103. beq $4,$65
  104. .align 4
  105. $66:
  106. EXI( ldq $1,0($7) )
  107. subq $4,8,$4
  108. EXO( stq $1,0($6) )
  109. addq $7,8,$7
  110. subq $0,8,$0
  111. addq $6,8,$6
  112. bne $4,$66
  113. $65:
  114. beq $0,$41
  115. EXI( ldq $2,0($7) )
  116. EXO( ldq $1,0($6) )
  117. mskql $2,$0,$2
  118. mskqh $1,$0,$1
  119. bis $2,$1,$2
  120. EXO( stq $2,0($6) )
  121. bis $31,$31,$0
  122. $41:
  123. $35:
  124. $exitout:
  125. ret $31,($28),1
  126. $exitin:
  127. /* A stupid byte-by-byte zeroing of the rest of the output
  128. buffer. This cures security holes by never leaving
  129. random kernel data around to be copied elsewhere. */
  130. mov $0,$1
  131. $101:
  132. EXO ( ldq_u $2,0($6) )
  133. subq $1,1,$1
  134. mskbl $2,$6,$2
  135. EXO ( stq_u $2,0($6) )
  136. addq $6,1,$6
  137. bgt $1,$101
  138. ret $31,($28),1
  139. .end __copy_user