0001
0002 #ifndef _SPARC64_FUTEX_H
0003 #define _SPARC64_FUTEX_H
0004
0005 #include <linux/futex.h>
0006 #include <linux/uaccess.h>
0007 #include <asm/errno.h>
0008
0009 #define __futex_cas_op(insn, ret, oldval, uaddr, oparg) \
0010 __asm__ __volatile__( \
0011 "\n1: lduwa [%3] %%asi, %2\n" \
0012 " " insn "\n" \
0013 "2: casa [%3] %%asi, %2, %1\n" \
0014 " cmp %2, %1\n" \
0015 " bne,pn %%icc, 1b\n" \
0016 " mov 0, %0\n" \
0017 "3:\n" \
0018 " .section .fixup,#alloc,#execinstr\n" \
0019 " .align 4\n" \
0020 "4: sethi %%hi(3b), %0\n" \
0021 " jmpl %0 + %%lo(3b), %%g0\n" \
0022 " mov %5, %0\n" \
0023 " .previous\n" \
0024 " .section __ex_table,\"a\"\n" \
0025 " .align 4\n" \
0026 " .word 1b, 4b\n" \
0027 " .word 2b, 4b\n" \
0028 " .previous\n" \
0029 : "=&r" (ret), "=&r" (oldval), "=&r" (tem) \
0030 : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
0031 : "memory")
0032
0033 static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
0034 u32 __user *uaddr)
0035 {
0036 int oldval = 0, ret, tem;
0037
0038 if (unlikely((((unsigned long) uaddr) & 0x3UL)))
0039 return -EINVAL;
0040
0041 switch (op) {
0042 case FUTEX_OP_SET:
0043 __futex_cas_op("mov\t%4, %1", ret, oldval, uaddr, oparg);
0044 break;
0045 case FUTEX_OP_ADD:
0046 __futex_cas_op("add\t%2, %4, %1", ret, oldval, uaddr, oparg);
0047 break;
0048 case FUTEX_OP_OR:
0049 __futex_cas_op("or\t%2, %4, %1", ret, oldval, uaddr, oparg);
0050 break;
0051 case FUTEX_OP_ANDN:
0052 __futex_cas_op("andn\t%2, %4, %1", ret, oldval, uaddr, oparg);
0053 break;
0054 case FUTEX_OP_XOR:
0055 __futex_cas_op("xor\t%2, %4, %1", ret, oldval, uaddr, oparg);
0056 break;
0057 default:
0058 ret = -ENOSYS;
0059 }
0060
0061 if (!ret)
0062 *oval = oldval;
0063
0064 return ret;
0065 }
0066
0067 static inline int
0068 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
0069 u32 oldval, u32 newval)
0070 {
0071 int ret = 0;
0072
0073 __asm__ __volatile__(
0074 "\n1: casa [%4] %%asi, %3, %1\n"
0075 "2:\n"
0076 " .section .fixup,#alloc,#execinstr\n"
0077 " .align 4\n"
0078 "3: sethi %%hi(2b), %0\n"
0079 " jmpl %0 + %%lo(2b), %%g0\n"
0080 " mov %5, %0\n"
0081 " .previous\n"
0082 " .section __ex_table,\"a\"\n"
0083 " .align 4\n"
0084 " .word 1b, 3b\n"
0085 " .previous\n"
0086 : "+r" (ret), "=r" (newval)
0087 : "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
0088 : "memory");
0089
0090 *uval = newval;
0091 return ret;
0092 }
0093
0094 #endif