blob: 1a944c18c53902645d4621c6ced9b37a34e90c32 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
David Gibson2ff2ae72005-11-02 13:58:22 +11002#ifndef _ASM_POWERPC_FUTEX_H
3#define _ASM_POWERPC_FUTEX_H
Jakub Jelinek4732efbe2005-09-06 15:16:25 -07004
5#ifdef __KERNEL__
6
7#include <linux/futex.h>
Jeff Dike730f4122008-04-30 00:54:49 -07008#include <linux/uaccess.h>
Jakub Jelinek4732efbe2005-09-06 15:16:25 -07009#include <asm/errno.h>
Becky Brucefeaf7cf2005-09-22 14:20:04 -050010#include <asm/synch.h>
David Gibson3ddfbcf2005-11-10 12:56:55 +110011#include <asm/asm-compat.h>
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070012
13#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
David Gibson2ff2ae72005-11-02 13:58:22 +110014 __asm__ __volatile ( \
Benjamin Herrenschmidtb97021f2011-11-15 17:11:27 +000015 PPC_ATOMIC_ENTRY_BARRIER \
David Gibson2ff2ae72005-11-02 13:58:22 +110016"1: lwarx %0,0,%2\n" \
17 insn \
David Gibson3ddfbcf2005-11-10 12:56:55 +110018 PPC405_ERR77(0, %2) \
David Gibson2ff2ae72005-11-02 13:58:22 +110019"2: stwcx. %1,0,%2\n" \
20 "bne- 1b\n" \
Benjamin Herrenschmidtb97021f2011-11-15 17:11:27 +000021 PPC_ATOMIC_EXIT_BARRIER \
David Gibson2ff2ae72005-11-02 13:58:22 +110022 "li %1,0\n" \
23"3: .section .fixup,\"ax\"\n" \
24"4: li %1,%3\n" \
25 "b 3b\n" \
26 ".previous\n" \
Nicholas Piggin24bfa6a2016-10-13 16:42:53 +110027 EX_TABLE(1b, 4b) \
28 EX_TABLE(2b, 4b) \
David Gibson2ff2ae72005-11-02 13:58:22 +110029 : "=&r" (oldval), "=&r" (ret) \
Paul Mackerras306a8282009-04-13 14:09:09 +000030 : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070031 : "cr0", "memory")
32
Jiri Slaby30d6e0a2017-08-24 09:31:05 +020033static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
34 u32 __user *uaddr)
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070035{
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070036 int oldval = 0, ret;
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070037
Peter Zijlstraa8663742006-12-06 20:32:20 -080038 pagefault_disable();
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070039
40 switch (op) {
41 case FUTEX_OP_SET:
Paul Mackerras306a8282009-04-13 14:09:09 +000042 __futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070043 break;
44 case FUTEX_OP_ADD:
Paul Mackerras306a8282009-04-13 14:09:09 +000045 __futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070046 break;
47 case FUTEX_OP_OR:
Paul Mackerras306a8282009-04-13 14:09:09 +000048 __futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070049 break;
50 case FUTEX_OP_ANDN:
Paul Mackerras306a8282009-04-13 14:09:09 +000051 __futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070052 break;
53 case FUTEX_OP_XOR:
Paul Mackerras306a8282009-04-13 14:09:09 +000054 __futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070055 break;
56 default:
57 ret = -ENOSYS;
58 }
59
Peter Zijlstraa8663742006-12-06 20:32:20 -080060 pagefault_enable();
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070061
Jiri Slaby30d6e0a2017-08-24 09:31:05 +020062 if (!ret)
63 *oval = oldval;
64
Jakub Jelinek4732efbe2005-09-06 15:16:25 -070065 return ret;
66}
67
Ingo Molnare9056f12006-03-27 01:16:21 -080068static inline int
Michel Lespinasse8d7718a2011-03-10 18:50:58 -080069futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
70 u32 oldval, u32 newval)
Ingo Molnare9056f12006-03-27 01:16:21 -080071{
Michel Lespinasse8d7718a2011-03-10 18:50:58 -080072 int ret = 0;
73 u32 prev;
David Woodhouse69588292006-09-04 21:53:14 -070074
Michel Lespinasse8d7718a2011-03-10 18:50:58 -080075 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
David Woodhouse69588292006-09-04 21:53:14 -070076 return -EFAULT;
77
78 __asm__ __volatile__ (
Benjamin Herrenschmidtb97021f2011-11-15 17:11:27 +000079 PPC_ATOMIC_ENTRY_BARRIER
Michel Lespinasse37a9d912011-03-10 18:48:51 -080080"1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
81 cmpw 0,%1,%4\n\
David Woodhouse69588292006-09-04 21:53:14 -070082 bne- 3f\n"
Michel Lespinasse37a9d912011-03-10 18:48:51 -080083 PPC405_ERR77(0,%3)
84"2: stwcx. %5,0,%3\n\
David Woodhouse69588292006-09-04 21:53:14 -070085 bne- 1b\n"
Benjamin Herrenschmidtb97021f2011-11-15 17:11:27 +000086 PPC_ATOMIC_EXIT_BARRIER
David Woodhouse69588292006-09-04 21:53:14 -070087"3: .section .fixup,\"ax\"\n\
Michel Lespinasse37a9d912011-03-10 18:48:51 -0800884: li %0,%6\n\
David Woodhouse69588292006-09-04 21:53:14 -070089 b 3b\n\
Nicholas Piggin24bfa6a2016-10-13 16:42:53 +110090 .previous\n"
91 EX_TABLE(1b, 4b)
92 EX_TABLE(2b, 4b)
Michel Lespinasse37a9d912011-03-10 18:48:51 -080093 : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
David Woodhouse69588292006-09-04 21:53:14 -070094 : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
95 : "cc", "memory");
96
Michel Lespinasse37a9d912011-03-10 18:48:51 -080097 *uval = prev;
98 return ret;
Ingo Molnare9056f12006-03-27 01:16:21 -080099}
100
David Gibson2ff2ae72005-11-02 13:58:22 +1100101#endif /* __KERNEL__ */
102#endif /* _ASM_POWERPC_FUTEX_H */