putuser_64.S 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * __put_user functions.
  3. *
  4. * (C) Copyright 1998 Linus Torvalds
  5. * (C) Copyright 2005 Andi Kleen
  6. *
  7. * These functions have a non-standard call interface
  8. * to make them more efficient, especially as they
  9. * return an error value in addition to the "real"
  10. * return value.
  11. */
  12. /*
  13. * __put_user_X
  14. *
  15. * Inputs: %rcx contains the address
  16. * %rdx contains new value
  17. *
  18. * Outputs: %rax is error code (0 or -EFAULT)
  19. *
  20. * %r8 is destroyed.
  21. *
  22. * These functions should not modify any other registers,
  23. * as they get called from within inline assembly.
  24. */
  25. #include <linux/linkage.h>
  26. #include <asm/dwarf2.h>
  27. #include <asm/page.h>
  28. #include <asm/errno.h>
  29. #include <asm/asm-offsets.h>
  30. #include <asm/thread_info.h>
  31. .text
  32. ENTRY(__put_user_1)
  33. CFI_STARTPROC
  34. GET_THREAD_INFO(%r8)
  35. cmpq threadinfo_addr_limit(%r8),%rcx
  36. jae bad_put_user
  37. 1: movb %dl,(%rcx)
  38. xorl %eax,%eax
  39. ret
  40. CFI_ENDPROC
  41. ENDPROC(__put_user_1)
  42. ENTRY(__put_user_2)
  43. CFI_STARTPROC
  44. GET_THREAD_INFO(%r8)
  45. addq $1,%rcx
  46. jc 20f
  47. cmpq threadinfo_addr_limit(%r8),%rcx
  48. jae 20f
  49. decq %rcx
  50. 2: movw %dx,(%rcx)
  51. xorl %eax,%eax
  52. ret
  53. 20: decq %rcx
  54. jmp bad_put_user
  55. CFI_ENDPROC
  56. ENDPROC(__put_user_2)
  57. ENTRY(__put_user_4)
  58. CFI_STARTPROC
  59. GET_THREAD_INFO(%r8)
  60. addq $3,%rcx
  61. jc 30f
  62. cmpq threadinfo_addr_limit(%r8),%rcx
  63. jae 30f
  64. subq $3,%rcx
  65. 3: movl %edx,(%rcx)
  66. xorl %eax,%eax
  67. ret
  68. 30: subq $3,%rcx
  69. jmp bad_put_user
  70. CFI_ENDPROC
  71. ENDPROC(__put_user_4)
  72. ENTRY(__put_user_8)
  73. CFI_STARTPROC
  74. GET_THREAD_INFO(%r8)
  75. addq $7,%rcx
  76. jc 40f
  77. cmpq threadinfo_addr_limit(%r8),%rcx
  78. jae 40f
  79. subq $7,%rcx
  80. 4: movq %rdx,(%rcx)
  81. xorl %eax,%eax
  82. ret
  83. 40: subq $7,%rcx
  84. jmp bad_put_user
  85. CFI_ENDPROC
  86. ENDPROC(__put_user_8)
  87. bad_put_user:
  88. CFI_STARTPROC
  89. movq $(-EFAULT),%rax
  90. ret
  91. CFI_ENDPROC
  92. END(bad_put_user)
  93. .section __ex_table,"a"
  94. .quad 1b,bad_put_user
  95. .quad 2b,bad_put_user
  96. .quad 3b,bad_put_user
  97. .quad 4b,bad_put_user
  98. .previous