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