futex.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  4. *
  5. * Vineetg: August 2010: From Android kernel work
  6. */
  7. #ifndef _ASM_FUTEX_H
  8. #define _ASM_FUTEX_H
  9. #include <linux/futex.h>
  10. #include <linux/preempt.h>
  11. #include <linux/uaccess.h>
  12. #include <asm/errno.h>
  13. #ifdef CONFIG_ARC_HAS_LLSC
  14. #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
  15. \
  16. smp_mb(); \
  17. __asm__ __volatile__( \
  18. "1: llock %1, [%2] \n" \
  19. insn "\n" \
  20. "2: scond %0, [%2] \n" \
  21. " bnz 1b \n" \
  22. " mov %0, 0 \n" \
  23. "3: \n" \
  24. " .section .fixup,\"ax\" \n" \
  25. " .align 4 \n" \
  26. "4: mov %0, %4 \n" \
  27. " j 3b \n" \
  28. " .previous \n" \
  29. " .section __ex_table,\"a\" \n" \
  30. " .align 4 \n" \
  31. " .word 1b, 4b \n" \
  32. " .word 2b, 4b \n" \
  33. " .previous \n" \
  34. \
  35. : "=&r" (ret), "=&r" (oldval) \
  36. : "r" (uaddr), "r" (oparg), "ir" (-EFAULT) \
  37. : "cc", "memory"); \
  38. smp_mb() \
  39. #else /* !CONFIG_ARC_HAS_LLSC */
  40. #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
  41. \
  42. smp_mb(); \
  43. __asm__ __volatile__( \
  44. "1: ld %1, [%2] \n" \
  45. insn "\n" \
  46. "2: st %0, [%2] \n" \
  47. " mov %0, 0 \n" \
  48. "3: \n" \
  49. " .section .fixup,\"ax\" \n" \
  50. " .align 4 \n" \
  51. "4: mov %0, %4 \n" \
  52. " j 3b \n" \
  53. " .previous \n" \
  54. " .section __ex_table,\"a\" \n" \
  55. " .align 4 \n" \
  56. " .word 1b, 4b \n" \
  57. " .word 2b, 4b \n" \
  58. " .previous \n" \
  59. \
  60. : "=&r" (ret), "=&r" (oldval) \
  61. : "r" (uaddr), "r" (oparg), "ir" (-EFAULT) \
  62. : "cc", "memory"); \
  63. smp_mb() \
  64. #endif
  65. static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
  66. u32 __user *uaddr)
  67. {
  68. int oldval = 0, ret;
  69. if (!access_ok(uaddr, sizeof(u32)))
  70. return -EFAULT;
  71. #ifndef CONFIG_ARC_HAS_LLSC
  72. preempt_disable(); /* to guarantee atomic r-m-w of futex op */
  73. #endif
  74. switch (op) {
  75. case FUTEX_OP_SET:
  76. __futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
  77. break;
  78. case FUTEX_OP_ADD:
  79. /* oldval = *uaddr; *uaddr += oparg ; ret = *uaddr */
  80. __futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
  81. break;
  82. case FUTEX_OP_OR:
  83. __futex_atomic_op("or %0, %1, %3", ret, oldval, uaddr, oparg);
  84. break;
  85. case FUTEX_OP_ANDN:
  86. __futex_atomic_op("bic %0, %1, %3", ret, oldval, uaddr, oparg);
  87. break;
  88. case FUTEX_OP_XOR:
  89. __futex_atomic_op("xor %0, %1, %3", ret, oldval, uaddr, oparg);
  90. break;
  91. default:
  92. ret = -ENOSYS;
  93. }
  94. #ifndef CONFIG_ARC_HAS_LLSC
  95. preempt_enable();
  96. #endif
  97. if (!ret)
  98. *oval = oldval;
  99. return ret;
  100. }
  101. /*
  102. * cmpxchg of futex (pagefaults disabled by caller)
  103. * Return 0 for success, -EFAULT otherwise
  104. */
  105. static inline int
  106. futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 expval,
  107. u32 newval)
  108. {
  109. int ret = 0;
  110. u32 existval;
  111. if (!access_ok(uaddr, sizeof(u32)))
  112. return -EFAULT;
  113. #ifndef CONFIG_ARC_HAS_LLSC
  114. preempt_disable(); /* to guarantee atomic r-m-w of futex op */
  115. #endif
  116. smp_mb();
  117. __asm__ __volatile__(
  118. #ifdef CONFIG_ARC_HAS_LLSC
  119. "1: llock %1, [%4] \n"
  120. " brne %1, %2, 3f \n"
  121. "2: scond %3, [%4] \n"
  122. " bnz 1b \n"
  123. #else
  124. "1: ld %1, [%4] \n"
  125. " brne %1, %2, 3f \n"
  126. "2: st %3, [%4] \n"
  127. #endif
  128. "3: \n"
  129. " .section .fixup,\"ax\" \n"
  130. "4: mov %0, %5 \n"
  131. " j 3b \n"
  132. " .previous \n"
  133. " .section __ex_table,\"a\" \n"
  134. " .align 4 \n"
  135. " .word 1b, 4b \n"
  136. " .word 2b, 4b \n"
  137. " .previous\n"
  138. : "+&r"(ret), "=&r"(existval)
  139. : "r"(expval), "r"(newval), "r"(uaddr), "ir"(-EFAULT)
  140. : "cc", "memory");
  141. smp_mb();
  142. #ifndef CONFIG_ARC_HAS_LLSC
  143. preempt_enable();
  144. #endif
  145. *uval = existval;
  146. return ret;
  147. }
  148. #endif