hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/arch/xtensa/include/asm/futex.h
....@@ -1,11 +1,8 @@
1
+/* SPDX-License-Identifier: GPL-2.0-only */
12 /*
23 * Atomic futex routines
34 *
45 * Based on the PowerPC implementataion
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 *
107 * Copyright (C) 2013 TangoTec Ltd.
118 *
....@@ -15,113 +12,152 @@
1512 #ifndef _ASM_XTENSA_FUTEX_H
1613 #define _ASM_XTENSA_FUTEX_H
1714
18
-#ifdef __KERNEL__
19
-
2015 #include <linux/futex.h>
2116 #include <linux/uaccess.h>
2217 #include <linux/errno.h>
2318
24
-#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
19
+#if XCHAL_HAVE_EXCLUSIVE
20
+#define __futex_atomic_op(insn, ret, old, uaddr, arg) \
2521 __asm__ __volatile( \
26
- "1: l32i %0, %2, 0\n" \
22
+ "1: l32ex %[oldval], %[addr]\n" \
2723 insn "\n" \
28
- " wsr %0, scompare1\n" \
29
- "2: s32c1i %1, %2, 0\n" \
30
- " bne %1, %0, 1b\n" \
31
- " movi %1, 0\n" \
24
+ "2: s32ex %[newval], %[addr]\n" \
25
+ " getex %[newval]\n" \
26
+ " beqz %[newval], 1b\n" \
27
+ " movi %[newval], 0\n" \
3228 "3:\n" \
3329 " .section .fixup,\"ax\"\n" \
3430 " .align 4\n" \
35
- "4: .long 3b\n" \
36
- "5: l32r %0, 4b\n" \
37
- " movi %1, %3\n" \
38
- " jx %0\n" \
31
+ " .literal_position\n" \
32
+ "5: movi %[oldval], 3b\n" \
33
+ " movi %[newval], %[fault]\n" \
34
+ " jx %[oldval]\n" \
3935 " .previous\n" \
4036 " .section __ex_table,\"a\"\n" \
41
- " .long 1b,5b,2b,5b\n" \
37
+ " .long 1b, 5b, 2b, 5b\n" \
4238 " .previous\n" \
43
- : "=&r" (oldval), "=&r" (ret) \
44
- : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
39
+ : [oldval] "=&r" (old), [newval] "=&r" (ret) \
40
+ : [addr] "r" (uaddr), [oparg] "r" (arg), \
41
+ [fault] "I" (-EFAULT) \
4542 : "memory")
43
+#elif XCHAL_HAVE_S32C1I
44
+#define __futex_atomic_op(insn, ret, old, uaddr, arg) \
45
+ __asm__ __volatile( \
46
+ "1: l32i %[oldval], %[mem]\n" \
47
+ insn "\n" \
48
+ " wsr %[oldval], scompare1\n" \
49
+ "2: s32c1i %[newval], %[mem]\n" \
50
+ " bne %[newval], %[oldval], 1b\n" \
51
+ " movi %[newval], 0\n" \
52
+ "3:\n" \
53
+ " .section .fixup,\"ax\"\n" \
54
+ " .align 4\n" \
55
+ " .literal_position\n" \
56
+ "5: movi %[oldval], 3b\n" \
57
+ " movi %[newval], %[fault]\n" \
58
+ " jx %[oldval]\n" \
59
+ " .previous\n" \
60
+ " .section __ex_table,\"a\"\n" \
61
+ " .long 1b, 5b, 2b, 5b\n" \
62
+ " .previous\n" \
63
+ : [oldval] "=&r" (old), [newval] "=&r" (ret), \
64
+ [mem] "+m" (*(uaddr)) \
65
+ : [oparg] "r" (arg), [fault] "I" (-EFAULT) \
66
+ : "memory")
67
+#endif
4668
4769 static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
4870 u32 __user *uaddr)
4971 {
72
+#if XCHAL_HAVE_S32C1I || XCHAL_HAVE_EXCLUSIVE
5073 int oldval = 0, ret;
5174
52
-#if !XCHAL_HAVE_S32C1I
53
- return -ENOSYS;
54
-#endif
55
-
56
- pagefault_disable();
75
+ if (!access_ok(uaddr, sizeof(u32)))
76
+ return -EFAULT;
5777
5878 switch (op) {
5979 case FUTEX_OP_SET:
60
- __futex_atomic_op("mov %1, %4", ret, oldval, uaddr, oparg);
80
+ __futex_atomic_op("mov %[newval], %[oparg]",
81
+ ret, oldval, uaddr, oparg);
6182 break;
6283 case FUTEX_OP_ADD:
63
- __futex_atomic_op("add %1, %0, %4", ret, oldval, uaddr,
64
- oparg);
84
+ __futex_atomic_op("add %[newval], %[oldval], %[oparg]",
85
+ ret, oldval, uaddr, oparg);
6586 break;
6687 case FUTEX_OP_OR:
67
- __futex_atomic_op("or %1, %0, %4", ret, oldval, uaddr,
68
- oparg);
88
+ __futex_atomic_op("or %[newval], %[oldval], %[oparg]",
89
+ ret, oldval, uaddr, oparg);
6990 break;
7091 case FUTEX_OP_ANDN:
71
- __futex_atomic_op("and %1, %0, %4", ret, oldval, uaddr,
72
- ~oparg);
92
+ __futex_atomic_op("and %[newval], %[oldval], %[oparg]",
93
+ ret, oldval, uaddr, ~oparg);
7394 break;
7495 case FUTEX_OP_XOR:
75
- __futex_atomic_op("xor %1, %0, %4", ret, oldval, uaddr,
76
- oparg);
96
+ __futex_atomic_op("xor %[newval], %[oldval], %[oparg]",
97
+ ret, oldval, uaddr, oparg);
7798 break;
7899 default:
79100 ret = -ENOSYS;
80101 }
81102
82
- pagefault_enable();
83
-
84103 if (!ret)
85104 *oval = oldval;
86105
87106 return ret;
107
+#else
108
+ return -ENOSYS;
109
+#endif
88110 }
89111
90112 static inline int
91113 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
92114 u32 oldval, u32 newval)
93115 {
116
+#if XCHAL_HAVE_S32C1I || XCHAL_HAVE_EXCLUSIVE
117
+ unsigned long tmp;
94118 int ret = 0;
95119
96
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
120
+ if (!access_ok(uaddr, sizeof(u32)))
97121 return -EFAULT;
98
-
99
-#if !XCHAL_HAVE_S32C1I
100
- return -ENOSYS;
101
-#endif
102122
103123 __asm__ __volatile__ (
104124 " # futex_atomic_cmpxchg_inatomic\n"
105
- " wsr %5, scompare1\n"
106
- "1: s32c1i %1, %4, 0\n"
107
- " s32i %1, %6, 0\n"
125
+#if XCHAL_HAVE_EXCLUSIVE
126
+ "1: l32ex %[tmp], %[addr]\n"
127
+ " s32i %[tmp], %[uval], 0\n"
128
+ " bne %[tmp], %[oldval], 2f\n"
129
+ " mov %[tmp], %[newval]\n"
130
+ "3: s32ex %[tmp], %[addr]\n"
131
+ " getex %[tmp]\n"
132
+ " beqz %[tmp], 1b\n"
133
+#elif XCHAL_HAVE_S32C1I
134
+ " wsr %[oldval], scompare1\n"
135
+ "1: s32c1i %[newval], %[addr], 0\n"
136
+ " s32i %[newval], %[uval], 0\n"
137
+#endif
108138 "2:\n"
109139 " .section .fixup,\"ax\"\n"
110140 " .align 4\n"
111
- "3: .long 2b\n"
112
- "4: l32r %1, 3b\n"
113
- " movi %0, %7\n"
114
- " jx %1\n"
141
+ " .literal_position\n"
142
+ "4: movi %[tmp], 2b\n"
143
+ " movi %[ret], %[fault]\n"
144
+ " jx %[tmp]\n"
115145 " .previous\n"
116146 " .section __ex_table,\"a\"\n"
117
- " .long 1b,4b\n"
147
+ " .long 1b, 4b\n"
148
+#if XCHAL_HAVE_EXCLUSIVE
149
+ " .long 3b, 4b\n"
150
+#endif
118151 " .previous\n"
119
- : "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval)
120
- : "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT)
152
+ : [ret] "+r" (ret), [newval] "+r" (newval), [tmp] "=&r" (tmp)
153
+ : [addr] "r" (uaddr), [oldval] "r" (oldval), [uval] "r" (uval),
154
+ [fault] "I" (-EFAULT)
121155 : "memory");
122156
123157 return ret;
158
+#else
159
+ return -ENOSYS;
160
+#endif
124161 }
125162
126
-#endif /* __KERNEL__ */
127163 #endif /* _ASM_XTENSA_FUTEX_H */