]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
77b4cf5c IK |
2 | #ifndef _ASM_ALPHA_FUTEX_H |
3 | #define _ASM_ALPHA_FUTEX_H | |
4732efbe | 4 | |
77b4cf5c | 5 | #ifdef __KERNEL__ |
4732efbe | 6 | |
77b4cf5c IK |
7 | #include <linux/futex.h> |
8 | #include <linux/uaccess.h> | |
9 | #include <asm/errno.h> | |
10 | #include <asm/barrier.h> | |
11 | ||
12 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | |
13 | __asm__ __volatile__( \ | |
14 | __ASM_SMP_MB \ | |
15 | "1: ldl_l %0,0(%2)\n" \ | |
16 | insn \ | |
17 | "2: stl_c %1,0(%2)\n" \ | |
18 | " beq %1,4f\n" \ | |
19 | " mov $31,%1\n" \ | |
20 | "3: .subsection 2\n" \ | |
21 | "4: br 1b\n" \ | |
22 | " .previous\n" \ | |
ca282f69 AV |
23 | EXC(1b,3b,%1,$31) \ |
24 | EXC(2b,3b,%1,$31) \ | |
77b4cf5c IK |
25 | : "=&r" (oldval), "=&r"(ret) \ |
26 | : "r" (uaddr), "r"(oparg) \ | |
27 | : "memory") | |
28 | ||
30d6e0a4 JS |
29 | static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, |
30 | u32 __user *uaddr) | |
77b4cf5c | 31 | { |
77b4cf5c | 32 | int oldval = 0, ret; |
77b4cf5c IK |
33 | |
34 | pagefault_disable(); | |
35 | ||
36 | switch (op) { | |
37 | case FUTEX_OP_SET: | |
38 | __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg); | |
39 | break; | |
40 | case FUTEX_OP_ADD: | |
41 | __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
42 | break; | |
43 | case FUTEX_OP_OR: | |
44 | __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
45 | break; | |
46 | case FUTEX_OP_ANDN: | |
47 | __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
48 | break; | |
49 | case FUTEX_OP_XOR: | |
50 | __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
51 | break; | |
52 | default: | |
53 | ret = -ENOSYS; | |
54 | } | |
55 | ||
56 | pagefault_enable(); | |
57 | ||
30d6e0a4 JS |
58 | if (!ret) |
59 | *oval = oldval; | |
60 | ||
77b4cf5c IK |
61 | return ret; |
62 | } | |
63 | ||
64 | static inline int | |
8d7718aa ML |
65 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
66 | u32 oldval, u32 newval) | |
77b4cf5c | 67 | { |
8d7718aa ML |
68 | int ret = 0, cmp; |
69 | u32 prev; | |
77b4cf5c | 70 | |
8d7718aa | 71 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
77b4cf5c IK |
72 | return -EFAULT; |
73 | ||
74 | __asm__ __volatile__ ( | |
75 | __ASM_SMP_MB | |
37a9d912 ML |
76 | "1: ldl_l %1,0(%3)\n" |
77 | " cmpeq %1,%4,%2\n" | |
78 | " beq %2,3f\n" | |
79 | " mov %5,%2\n" | |
80 | "2: stl_c %2,0(%3)\n" | |
81 | " beq %2,4f\n" | |
77b4cf5c IK |
82 | "3: .subsection 2\n" |
83 | "4: br 1b\n" | |
84 | " .previous\n" | |
ca282f69 AV |
85 | EXC(1b,3b,%0,$31) |
86 | EXC(2b,3b,%0,$31) | |
37a9d912 | 87 | : "+r"(ret), "=&r"(prev), "=&r"(cmp) |
62aca403 | 88 | : "r"(uaddr), "r"((long)(int)oldval), "r"(newval) |
77b4cf5c IK |
89 | : "memory"); |
90 | ||
37a9d912 ML |
91 | *uval = prev; |
92 | return ret; | |
77b4cf5c IK |
93 | } |
94 | ||
95 | #endif /* __KERNEL__ */ | |
96 | #endif /* _ASM_ALPHA_FUTEX_H */ |