1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2b8b572e1SStephen Rothwell #ifndef _ASM_POWERPC_FUTEX_H
3b8b572e1SStephen Rothwell #define _ASM_POWERPC_FUTEX_H
4b8b572e1SStephen Rothwell
5b8b572e1SStephen Rothwell #ifdef __KERNEL__
6b8b572e1SStephen Rothwell
7b8b572e1SStephen Rothwell #include <linux/futex.h>
8b8b572e1SStephen Rothwell #include <linux/uaccess.h>
9b8b572e1SStephen Rothwell #include <asm/errno.h>
10b8b572e1SStephen Rothwell #include <asm/synch.h>
11b8b572e1SStephen Rothwell
12b8b572e1SStephen Rothwell #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
13b8b572e1SStephen Rothwell __asm__ __volatile ( \
14b97021f8SBenjamin Herrenschmidt PPC_ATOMIC_ENTRY_BARRIER \
15b8b572e1SStephen Rothwell "1: lwarx %0,0,%2\n" \
16b8b572e1SStephen Rothwell insn \
17b8b572e1SStephen Rothwell "2: stwcx. %1,0,%2\n" \
18b8b572e1SStephen Rothwell "bne- 1b\n" \
19b97021f8SBenjamin Herrenschmidt PPC_ATOMIC_EXIT_BARRIER \
20b8b572e1SStephen Rothwell "li %1,0\n" \
21b8b572e1SStephen Rothwell "3: .section .fixup,\"ax\"\n" \
22b8b572e1SStephen Rothwell "4: li %1,%3\n" \
23b8b572e1SStephen Rothwell "b 3b\n" \
24b8b572e1SStephen Rothwell ".previous\n" \
2524bfa6a9SNicholas Piggin EX_TABLE(1b, 4b) \
2624bfa6a9SNicholas Piggin EX_TABLE(2b, 4b) \
27b8b572e1SStephen Rothwell : "=&r" (oldval), "=&r" (ret) \
28306a8288SPaul Mackerras : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
29b8b572e1SStephen Rothwell : "cr0", "memory")
30b8b572e1SStephen Rothwell
arch_futex_atomic_op_inuser(int op,int oparg,int * oval,u32 __user * uaddr)3130d6e0a4SJiri Slaby static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
3230d6e0a4SJiri Slaby u32 __user *uaddr)
33b8b572e1SStephen Rothwell {
34b8b572e1SStephen Rothwell int oldval = 0, ret;
35b8b572e1SStephen Rothwell
36*870779f4SChristophe Leroy if (!user_access_begin(uaddr, sizeof(u32)))
37a08971e9SAl Viro return -EFAULT;
38b8b572e1SStephen Rothwell
39b8b572e1SStephen Rothwell switch (op) {
40b8b572e1SStephen Rothwell case FUTEX_OP_SET:
41306a8288SPaul Mackerras __futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
42b8b572e1SStephen Rothwell break;
43b8b572e1SStephen Rothwell case FUTEX_OP_ADD:
44306a8288SPaul Mackerras __futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
45b8b572e1SStephen Rothwell break;
46b8b572e1SStephen Rothwell case FUTEX_OP_OR:
47306a8288SPaul Mackerras __futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
48b8b572e1SStephen Rothwell break;
49b8b572e1SStephen Rothwell case FUTEX_OP_ANDN:
50306a8288SPaul Mackerras __futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
51b8b572e1SStephen Rothwell break;
52b8b572e1SStephen Rothwell case FUTEX_OP_XOR:
53306a8288SPaul Mackerras __futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
54b8b572e1SStephen Rothwell break;
55b8b572e1SStephen Rothwell default:
56b8b572e1SStephen Rothwell ret = -ENOSYS;
57b8b572e1SStephen Rothwell }
58*870779f4SChristophe Leroy user_access_end();
59b8b572e1SStephen Rothwell
6030d6e0a4SJiri Slaby *oval = oldval;
6130d6e0a4SJiri Slaby
62b8b572e1SStephen Rothwell return ret;
63b8b572e1SStephen Rothwell }
64b8b572e1SStephen Rothwell
65b8b572e1SStephen Rothwell static inline int
futex_atomic_cmpxchg_inatomic(u32 * uval,u32 __user * uaddr,u32 oldval,u32 newval)668d7718aaSMichel Lespinasse futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
678d7718aaSMichel Lespinasse u32 oldval, u32 newval)
68b8b572e1SStephen Rothwell {
698d7718aaSMichel Lespinasse int ret = 0;
708d7718aaSMichel Lespinasse u32 prev;
71b8b572e1SStephen Rothwell
72*870779f4SChristophe Leroy if (!user_access_begin(uaddr, sizeof(u32)))
73b8b572e1SStephen Rothwell return -EFAULT;
74b8b572e1SStephen Rothwell
75b8b572e1SStephen Rothwell __asm__ __volatile__ (
76b97021f8SBenjamin Herrenschmidt PPC_ATOMIC_ENTRY_BARRIER
7737a9d912SMichel Lespinasse "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
7837a9d912SMichel Lespinasse cmpw 0,%1,%4\n\
79b8b572e1SStephen Rothwell bne- 3f\n"
8037a9d912SMichel Lespinasse "2: stwcx. %5,0,%3\n\
81b8b572e1SStephen Rothwell bne- 1b\n"
82b97021f8SBenjamin Herrenschmidt PPC_ATOMIC_EXIT_BARRIER
83b8b572e1SStephen Rothwell "3: .section .fixup,\"ax\"\n\
8437a9d912SMichel Lespinasse 4: li %0,%6\n\
85b8b572e1SStephen Rothwell b 3b\n\
8624bfa6a9SNicholas Piggin .previous\n"
8724bfa6a9SNicholas Piggin EX_TABLE(1b, 4b)
8824bfa6a9SNicholas Piggin EX_TABLE(2b, 4b)
8937a9d912SMichel Lespinasse : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
90b8b572e1SStephen Rothwell : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
91b8b572e1SStephen Rothwell : "cc", "memory");
92b8b572e1SStephen Rothwell
93*870779f4SChristophe Leroy user_access_end();
94*870779f4SChristophe Leroy
9537a9d912SMichel Lespinasse *uval = prev;
969dc086f1SMichael Ellerman
9737a9d912SMichel Lespinasse return ret;
98b8b572e1SStephen Rothwell }
99b8b572e1SStephen Rothwell
100b8b572e1SStephen Rothwell #endif /* __KERNEL__ */
101b8b572e1SStephen Rothwell #endif /* _ASM_POWERPC_FUTEX_H */
102