futex.h 2.1 KB

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