xref: /openbmc/linux/arch/powerpc/include/asm/futex.h (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
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