futex.h 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_S390_FUTEX_H
  3. #define _ASM_S390_FUTEX_H
  4. #include <linux/uaccess.h>
  5. #include <linux/futex.h>
  6. #include <asm/asm-extable.h>
  7. #include <asm/mmu_context.h>
  8. #include <asm/errno.h>
  9. #define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \
  10. asm volatile( \
  11. " sacf 256\n" \
  12. "0: l %1,0(%6)\n" \
  13. "1:"insn \
  14. "2: cs %1,%2,0(%6)\n" \
  15. "3: jl 1b\n" \
  16. " lhi %0,0\n" \
  17. "4: sacf 768\n" \
  18. EX_TABLE(0b,4b) EX_TABLE(1b,4b) \
  19. EX_TABLE(2b,4b) EX_TABLE(3b,4b) \
  20. : "=d" (ret), "=&d" (oldval), "=&d" (newval), \
  21. "=m" (*uaddr) \
  22. : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
  23. "m" (*uaddr) : "cc");
  24. static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
  25. u32 __user *uaddr)
  26. {
  27. int oldval = 0, newval, ret;
  28. switch (op) {
  29. case FUTEX_OP_SET:
  30. __futex_atomic_op("lr %2,%5\n",
  31. ret, oldval, newval, uaddr, oparg);
  32. break;
  33. case FUTEX_OP_ADD:
  34. __futex_atomic_op("lr %2,%1\nar %2,%5\n",
  35. ret, oldval, newval, uaddr, oparg);
  36. break;
  37. case FUTEX_OP_OR:
  38. __futex_atomic_op("lr %2,%1\nor %2,%5\n",
  39. ret, oldval, newval, uaddr, oparg);
  40. break;
  41. case FUTEX_OP_ANDN:
  42. __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
  43. ret, oldval, newval, uaddr, oparg);
  44. break;
  45. case FUTEX_OP_XOR:
  46. __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
  47. ret, oldval, newval, uaddr, oparg);
  48. break;
  49. default:
  50. ret = -ENOSYS;
  51. }
  52. if (!ret)
  53. *oval = oldval;
  54. return ret;
  55. }
  56. static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  57. u32 oldval, u32 newval)
  58. {
  59. int ret;
  60. asm volatile(
  61. " sacf 256\n"
  62. "0: cs %1,%4,0(%5)\n"
  63. "1: la %0,0\n"
  64. "2: sacf 768\n"
  65. EX_TABLE(0b,2b) EX_TABLE(1b,2b)
  66. : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
  67. : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
  68. : "cc", "memory");
  69. *uval = oldval;
  70. return ret;
  71. }
  72. #endif /* _ASM_S390_FUTEX_H */