^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_FUTEX_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _ASM_FUTEX_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/futex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) register unsigned long r8 __asm ("r8") = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) __asm__ __volatile__( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) " mf;; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) "[1:] " insn ";; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) " .xdata4 \"__ex_table\", 1b-., 2f-. \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) "[2:]" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) : "+r" (r8), "=r" (oldval) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) : "r" (uaddr), "r" (oparg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) : "memory"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ret = r8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) register unsigned long r8 __asm ("r8") = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int val, newval; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) __asm__ __volatile__( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) " mf;; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) "[1:] ld4 %3=[%4];; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) " mov %2=%3 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) insn ";; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) " mov ar.ccv=%2;; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) "[2:] cmpxchg4.acq %1=[%4],%3,ar.ccv;; \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) " .xdata4 \"__ex_table\", 1b-., 3f-.\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) " .xdata4 \"__ex_table\", 2b-., 3f-.\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) "[3:]" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) : "+r" (r8), "=r" (val), "=&r" (oldval), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "=&r" (newval) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) : "r" (uaddr), "r" (oparg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) : "memory"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (unlikely (r8)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) } while (unlikely (val != oldval)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = r8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int oldval = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (!access_ok(uaddr, sizeof(u32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case FUTEX_OP_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __futex_atomic_op1("xchg4 %1=[%2],%3", ret, oldval, uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case FUTEX_OP_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) __futex_atomic_op2("add %3=%3,%5", ret, oldval, uaddr, oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case FUTEX_OP_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) __futex_atomic_op2("or %3=%3,%5", ret, oldval, uaddr, oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case FUTEX_OP_ANDN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) __futex_atomic_op2("and %3=%3,%5", ret, oldval, uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ~oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case FUTEX_OP_XOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __futex_atomic_op2("xor %3=%3,%5", ret, oldval, uaddr, oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ret = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) *oval = oldval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 oldval, u32 newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!access_ok(uaddr, sizeof(u32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) register unsigned long r8 __asm ("r8") = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned long prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) " mf;; \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) " mov ar.ccv=%4;; \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) " .xdata4 \"__ex_table\", 1b-., 2f-. \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) "[2:]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) : "+r" (r8), "=&r" (prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) : "r" (uaddr), "r" (newval),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "rO" ((long) (unsigned) oldval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *uval = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return r8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #endif /* _ASM_FUTEX_H */