Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
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 /* !(_SPARC64_FUTEX_H) */