powerpc/mm: Fixup tlbie vs mtpidr/mtlpidr ordering issue on POWER9
[linux-2.6-block.git] / arch / powerpc / include / asm / futex.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
2ff2ae7a
DG
2#ifndef _ASM_POWERPC_FUTEX_H
3#define _ASM_POWERPC_FUTEX_H
4732efbe
JJ
4
5#ifdef __KERNEL__
6
7#include <linux/futex.h>
730f412c 8#include <linux/uaccess.h>
4732efbe 9#include <asm/errno.h>
feaf7cf1 10#include <asm/synch.h>
36a7eeaf 11#include <asm/asm-405.h>
4732efbe
JJ
12
13#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
2ff2ae7a 14 __asm__ __volatile ( \
b97021f8 15 PPC_ATOMIC_ENTRY_BARRIER \
2ff2ae7a
DG
16"1: lwarx %0,0,%2\n" \
17 insn \
3ddfbcf1 18 PPC405_ERR77(0, %2) \
2ff2ae7a
DG
19"2: stwcx. %1,0,%2\n" \
20 "bne- 1b\n" \
b97021f8 21 PPC_ATOMIC_EXIT_BARRIER \
2ff2ae7a
DG
22 "li %1,0\n" \
23"3: .section .fixup,\"ax\"\n" \
24"4: li %1,%3\n" \
25 "b 3b\n" \
26 ".previous\n" \
24bfa6a9
NP
27 EX_TABLE(1b, 4b) \
28 EX_TABLE(2b, 4b) \
2ff2ae7a 29 : "=&r" (oldval), "=&r" (ret) \
306a8288 30 : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
4732efbe
JJ
31 : "cr0", "memory")
32
30d6e0a4
JS
33static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
34 u32 __user *uaddr)
4732efbe 35{
4732efbe 36 int oldval = 0, ret;
4732efbe 37
de78a9c4 38 allow_write_to_user(uaddr, sizeof(*uaddr));
a866374a 39 pagefault_disable();
4732efbe
JJ
40
41 switch (op) {
42 case FUTEX_OP_SET:
306a8288 43 __futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
4732efbe
JJ
44 break;
45 case FUTEX_OP_ADD:
306a8288 46 __futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
4732efbe
JJ
47 break;
48 case FUTEX_OP_OR:
306a8288 49 __futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
4732efbe
JJ
50 break;
51 case FUTEX_OP_ANDN:
306a8288 52 __futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
4732efbe
JJ
53 break;
54 case FUTEX_OP_XOR:
306a8288 55 __futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
4732efbe
JJ
56 break;
57 default:
58 ret = -ENOSYS;
59 }
60
a866374a 61 pagefault_enable();
4732efbe 62
38a0d0cd 63 *oval = oldval;
30d6e0a4 64
de78a9c4 65 prevent_write_to_user(uaddr, sizeof(*uaddr));
4732efbe
JJ
66 return ret;
67}
68
e9056f13 69static inline int
8d7718aa
ML
70futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
71 u32 oldval, u32 newval)
e9056f13 72{
8d7718aa
ML
73 int ret = 0;
74 u32 prev;
69588298 75
96d4f267 76 if (!access_ok(uaddr, sizeof(u32)))
69588298
DW
77 return -EFAULT;
78
de78a9c4 79 allow_write_to_user(uaddr, sizeof(*uaddr));
69588298 80 __asm__ __volatile__ (
b97021f8 81 PPC_ATOMIC_ENTRY_BARRIER
37a9d912
ML
82"1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
83 cmpw 0,%1,%4\n\
69588298 84 bne- 3f\n"
37a9d912
ML
85 PPC405_ERR77(0,%3)
86"2: stwcx. %5,0,%3\n\
69588298 87 bne- 1b\n"
b97021f8 88 PPC_ATOMIC_EXIT_BARRIER
69588298 89"3: .section .fixup,\"ax\"\n\
37a9d912 904: li %0,%6\n\
69588298 91 b 3b\n\
24bfa6a9
NP
92 .previous\n"
93 EX_TABLE(1b, 4b)
94 EX_TABLE(2b, 4b)
37a9d912 95 : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
69588298
DW
96 : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
97 : "cc", "memory");
98
37a9d912 99 *uval = prev;
de78a9c4 100 prevent_write_to_user(uaddr, sizeof(*uaddr));
37a9d912 101 return ret;
e9056f13
IM
102}
103
2ff2ae7a
DG
104#endif /* __KERNEL__ */
105#endif /* _ASM_POWERPC_FUTEX_H */