]>
Commit | Line | Data |
---|---|---|
fd3db0a6 MS |
1 | #ifndef _ASM_MICROBLAZE_FUTEX_H |
2 | #define _ASM_MICROBLAZE_FUTEX_H | |
3 | ||
4 | #ifdef __KERNEL__ | |
5 | ||
6 | #include <linux/futex.h> | |
7 | #include <linux/uaccess.h> | |
8 | #include <asm/errno.h> | |
9 | ||
10 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | |
11 | ({ \ | |
12 | __asm__ __volatile__ ( \ | |
13 | "1: lwx %0, %2, r0; " \ | |
14 | insn \ | |
15 | "2: swx %1, %2, r0; \ | |
16 | addic %1, r0, 0; \ | |
17 | bnei %1, 1b; \ | |
18 | 3: \ | |
19 | .section .fixup,\"ax\"; \ | |
20 | 4: brid 3b; \ | |
21 | addik %1, r0, %3; \ | |
22 | .previous; \ | |
23 | .section __ex_table,\"a\"; \ | |
24 | .word 1b,4b,2b,4b; \ | |
25 | .previous;" \ | |
26 | : "=&r" (oldval), "=&r" (ret) \ | |
8cf662ed | 27 | : "r" (uaddr), "i" (-EFAULT), "r" (oparg) \ |
fd3db0a6 MS |
28 | ); \ |
29 | }) | |
30 | ||
31 | static inline int | |
5961958c | 32 | arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) |
fd3db0a6 | 33 | { |
fd3db0a6 | 34 | int oldval = 0, ret; |
fd3db0a6 MS |
35 | |
36 | pagefault_disable(); | |
37 | ||
38 | switch (op) { | |
39 | case FUTEX_OP_SET: | |
40 | __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg); | |
41 | break; | |
42 | case FUTEX_OP_ADD: | |
43 | __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg); | |
44 | break; | |
45 | case FUTEX_OP_OR: | |
46 | __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg); | |
47 | break; | |
48 | case FUTEX_OP_ANDN: | |
4bb30baa | 49 | __futex_atomic_op("andn %1,%0,%4;", ret, oldval, uaddr, oparg); |
fd3db0a6 MS |
50 | break; |
51 | case FUTEX_OP_XOR: | |
52 | __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg); | |
53 | break; | |
54 | default: | |
55 | ret = -ENOSYS; | |
56 | } | |
57 | ||
58 | pagefault_enable(); | |
59 | ||
5961958c JS |
60 | if (!ret) |
61 | *oval = oldval; | |
62 | ||
fd3db0a6 MS |
63 | return ret; |
64 | } | |
65 | ||
66 | static inline int | |
8d7718aa ML |
67 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
68 | u32 oldval, u32 newval) | |
fd3db0a6 | 69 | { |
8d7718aa ML |
70 | int ret = 0, cmp; |
71 | u32 prev; | |
fd3db0a6 | 72 | |
8d7718aa | 73 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
fd3db0a6 MS |
74 | return -EFAULT; |
75 | ||
37a9d912 ML |
76 | __asm__ __volatile__ ("1: lwx %1, %3, r0; \ |
77 | cmp %2, %1, %4; \ | |
f6a12a7d | 78 | bnei %2, 3f; \ |
37a9d912 ML |
79 | 2: swx %5, %3, r0; \ |
80 | addic %2, r0, 0; \ | |
81 | bnei %2, 1b; \ | |
fd3db0a6 MS |
82 | 3: \ |
83 | .section .fixup,\"ax\"; \ | |
84 | 4: brid 3b; \ | |
37a9d912 | 85 | addik %0, r0, %6; \ |
fd3db0a6 MS |
86 | .previous; \ |
87 | .section __ex_table,\"a\"; \ | |
88 | .word 1b,4b,2b,4b; \ | |
89 | .previous;" \ | |
37a9d912 | 90 | : "+r" (ret), "=&r" (prev), "=&r"(cmp) \ |
fd3db0a6 MS |
91 | : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)); |
92 | ||
37a9d912 ML |
93 | *uval = prev; |
94 | return ret; | |
fd3db0a6 MS |
95 | } |
96 | ||
97 | #endif /* __KERNEL__ */ | |
98 | ||
99 | #endif |