Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_ALPHA_FUTEX_H
0003 #define _ASM_ALPHA_FUTEX_H
0004 
0005 #ifdef __KERNEL__
0006 
0007 #include <linux/futex.h>
0008 #include <linux/uaccess.h>
0009 #include <asm/errno.h>
0010 #include <asm/barrier.h>
0011 
0012 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)  \
0013     __asm__ __volatile__(                   \
0014         __ASM_SMP_MB                    \
0015     "1: ldl_l   %0,0(%2)\n"             \
0016         insn                        \
0017     "2: stl_c   %1,0(%2)\n"             \
0018     "   beq %1,4f\n"                \
0019     "   mov $31,%1\n"               \
0020     "3: .subsection 2\n"                \
0021     "4: br  1b\n"                   \
0022     "   .previous\n"                    \
0023     EXC(1b,3b,$31,%1)                   \
0024     EXC(2b,3b,$31,%1)                   \
0025     :   "=&r" (oldval), "=&r"(ret)          \
0026     :   "r" (uaddr), "r"(oparg)             \
0027     :   "memory")
0028 
0029 static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
0030         u32 __user *uaddr)
0031 {
0032     int oldval = 0, ret;
0033 
0034     if (!access_ok(uaddr, sizeof(u32)))
0035         return -EFAULT;
0036 
0037     switch (op) {
0038     case FUTEX_OP_SET:
0039         __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg);
0040         break;
0041     case FUTEX_OP_ADD:
0042         __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg);
0043         break;
0044     case FUTEX_OP_OR:
0045         __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg);
0046         break;
0047     case FUTEX_OP_ANDN:
0048         __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg);
0049         break;
0050     case FUTEX_OP_XOR:
0051         __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg);
0052         break;
0053     default:
0054         ret = -ENOSYS;
0055     }
0056 
0057     if (!ret)
0058         *oval = oldval;
0059 
0060     return ret;
0061 }
0062 
0063 static inline int
0064 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
0065                   u32 oldval, u32 newval)
0066 {
0067     int ret = 0, cmp;
0068     u32 prev;
0069 
0070     if (!access_ok(uaddr, sizeof(u32)))
0071         return -EFAULT;
0072 
0073     __asm__ __volatile__ (
0074         __ASM_SMP_MB
0075     "1: ldl_l   %1,0(%3)\n"
0076     "   cmpeq   %1,%4,%2\n"
0077     "   beq %2,3f\n"
0078     "   mov %5,%2\n"
0079     "2: stl_c   %2,0(%3)\n"
0080     "   beq %2,4f\n"
0081     "3: .subsection 2\n"
0082     "4: br  1b\n"
0083     "   .previous\n"
0084     EXC(1b,3b,$31,%0)
0085     EXC(2b,3b,$31,%0)
0086     :   "+r"(ret), "=&r"(prev), "=&r"(cmp)
0087     :   "r"(uaddr), "r"((long)(int)oldval), "r"(newval)
0088     :   "memory");
0089 
0090     *uval = prev;
0091     return ret;
0092 }
0093 
0094 #endif /* __KERNEL__ */
0095 #endif /* _ASM_ALPHA_FUTEX_H */