0001
0002 #ifndef _ASM_POWERPC_FUTEX_H
0003 #define _ASM_POWERPC_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/synch.h>
0011
0012 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
0013 __asm__ __volatile ( \
0014 PPC_ATOMIC_ENTRY_BARRIER \
0015 "1: lwarx %0,0,%2\n" \
0016 insn \
0017 "2: stwcx. %1,0,%2\n" \
0018 "bne- 1b\n" \
0019 PPC_ATOMIC_EXIT_BARRIER \
0020 "li %1,0\n" \
0021 "3: .section .fixup,\"ax\"\n" \
0022 "4: li %1,%3\n" \
0023 "b 3b\n" \
0024 ".previous\n" \
0025 EX_TABLE(1b, 4b) \
0026 EX_TABLE(2b, 4b) \
0027 : "=&r" (oldval), "=&r" (ret) \
0028 : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
0029 : "cr0", "memory")
0030
0031 static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
0032 u32 __user *uaddr)
0033 {
0034 int oldval = 0, ret;
0035
0036 if (!user_access_begin(uaddr, sizeof(u32)))
0037 return -EFAULT;
0038
0039 switch (op) {
0040 case FUTEX_OP_SET:
0041 __futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
0042 break;
0043 case FUTEX_OP_ADD:
0044 __futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
0045 break;
0046 case FUTEX_OP_OR:
0047 __futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
0048 break;
0049 case FUTEX_OP_ANDN:
0050 __futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
0051 break;
0052 case FUTEX_OP_XOR:
0053 __futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
0054 break;
0055 default:
0056 ret = -ENOSYS;
0057 }
0058 user_access_end();
0059
0060 *oval = oldval;
0061
0062 return ret;
0063 }
0064
0065 static inline int
0066 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
0067 u32 oldval, u32 newval)
0068 {
0069 int ret = 0;
0070 u32 prev;
0071
0072 if (!user_access_begin(uaddr, sizeof(u32)))
0073 return -EFAULT;
0074
0075 __asm__ __volatile__ (
0076 PPC_ATOMIC_ENTRY_BARRIER
0077 "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
0078 cmpw 0,%1,%4\n\
0079 bne- 3f\n"
0080 "2: stwcx. %5,0,%3\n\
0081 bne- 1b\n"
0082 PPC_ATOMIC_EXIT_BARRIER
0083 "3: .section .fixup,\"ax\"\n\
0084 4: li %0,%6\n\
0085 b 3b\n\
0086 .previous\n"
0087 EX_TABLE(1b, 4b)
0088 EX_TABLE(2b, 4b)
0089 : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
0090 : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
0091 : "cc", "memory");
0092
0093 user_access_end();
0094
0095 *uval = prev;
0096
0097 return ret;
0098 }
0099
0100 #endif
0101 #endif