^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_OPENRISC_FUTEX_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define __ASM_OPENRISC_FUTEX_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #ifdef __KERNEL__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/futex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) __asm__ __volatile__ ( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) "1: l.lwa %0, %2 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) insn "\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) "2: l.swa %2, %1 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) " l.bnf 1b \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) " l.ori %1, r0, 0 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) "3: \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ".section .fixup,\"ax\" \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) "4: l.j 3b \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) " l.addi %1, r0, %3 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ".previous \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) ".section __ex_table,\"a\" \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) ".word 1b,4b,2b,4b \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ".previous \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) : "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) : "i" (-EFAULT), "r" (oparg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) : "cc", "memory" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int oldval = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!access_ok(uaddr, sizeof(u32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case FUTEX_OP_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) __futex_atomic_op("l.or %1,%4,%4", ret, oldval, 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_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) __futex_atomic_op("l.add %1,%0,%4", ret, oldval, uaddr, oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case FUTEX_OP_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) __futex_atomic_op("l.or %1,%0,%4", ret, oldval, uaddr, oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case FUTEX_OP_ANDN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) __futex_atomic_op("l.and %1,%0,%4", ret, oldval, uaddr, ~oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) case FUTEX_OP_XOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) __futex_atomic_op("l.xor %1,%0,%4", ret, oldval, uaddr, oparg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ret = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *oval = oldval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 oldval, u32 newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u32 prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!access_ok(uaddr, sizeof(u32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) __asm__ __volatile__ ( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "1: l.lwa %1, %2 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) " l.sfeq %1, %3 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) " l.bnf 3f \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) " l.nop \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "2: l.swa %2, %4 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) " l.bnf 1b \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) " l.nop \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "3: \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ".section .fixup,\"ax\" \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "4: l.j 3b \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) " l.addi %0, r0, %5 \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ".previous \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ".section __ex_table,\"a\" \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ".word 1b,4b,2b,4b \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ".previous \n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) : "+r" (ret), "=&r" (prev), "+m" (*uaddr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) : "r" (oldval), "r" (newval), "i" (-EFAULT) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) : "cc", "memory" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *uval = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #endif /* __KERNEL__ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #endif /* __ASM_OPENRISC_FUTEX_H */