hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/xtensa/include/asm/cmpxchg.h
....@@ -13,6 +13,7 @@
1313
1414 #ifndef __ASSEMBLY__
1515
16
+#include <linux/bits.h>
1617 #include <linux/stringify.h>
1718
1819 /*
....@@ -22,12 +23,29 @@
2223 static inline unsigned long
2324 __cmpxchg_u32(volatile int *p, int old, int new)
2425 {
25
-#if XCHAL_HAVE_S32C1I
26
+#if XCHAL_HAVE_EXCLUSIVE
27
+ unsigned long tmp, result;
28
+
2629 __asm__ __volatile__(
27
- " wsr %2, scompare1\n"
28
- " s32c1i %0, %1, 0\n"
29
- : "+a" (new)
30
- : "a" (p), "a" (old)
30
+ "1: l32ex %[result], %[addr]\n"
31
+ " bne %[result], %[cmp], 2f\n"
32
+ " mov %[tmp], %[new]\n"
33
+ " s32ex %[tmp], %[addr]\n"
34
+ " getex %[tmp]\n"
35
+ " beqz %[tmp], 1b\n"
36
+ "2:\n"
37
+ : [result] "=&a" (result), [tmp] "=&a" (tmp)
38
+ : [new] "a" (new), [addr] "a" (p), [cmp] "a" (old)
39
+ : "memory"
40
+ );
41
+
42
+ return result;
43
+#elif XCHAL_HAVE_S32C1I
44
+ __asm__ __volatile__(
45
+ " wsr %[cmp], scompare1\n"
46
+ " s32c1i %[new], %[mem]\n"
47
+ : [new] "+a" (new), [mem] "+m" (*p)
48
+ : [cmp] "a" (old)
3149 : "memory"
3250 );
3351
....@@ -35,14 +53,14 @@
3553 #else
3654 __asm__ __volatile__(
3755 " rsil a15, "__stringify(TOPLEVEL)"\n"
38
- " l32i %0, %1, 0\n"
39
- " bne %0, %2, 1f\n"
40
- " s32i %3, %1, 0\n"
56
+ " l32i %[old], %[mem]\n"
57
+ " bne %[old], %[cmp], 1f\n"
58
+ " s32i %[new], %[mem]\n"
4159 "1:\n"
4260 " wsr a15, ps\n"
4361 " rsync\n"
44
- : "=&a" (old)
45
- : "a" (p), "a" (old), "r" (new)
62
+ : [old] "=&a" (old), [mem] "+m" (*p)
63
+ : [cmp] "a" (old), [new] "r" (new)
4664 : "a15", "memory");
4765 return old;
4866 #endif
....@@ -107,16 +125,32 @@
107125
108126 static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
109127 {
110
-#if XCHAL_HAVE_S32C1I
128
+#if XCHAL_HAVE_EXCLUSIVE
129
+ unsigned long tmp, result;
130
+
131
+ __asm__ __volatile__(
132
+ "1: l32ex %[result], %[addr]\n"
133
+ " mov %[tmp], %[val]\n"
134
+ " s32ex %[tmp], %[addr]\n"
135
+ " getex %[tmp]\n"
136
+ " beqz %[tmp], 1b\n"
137
+ : [result] "=&a" (result), [tmp] "=&a" (tmp)
138
+ : [val] "a" (val), [addr] "a" (m)
139
+ : "memory"
140
+ );
141
+
142
+ return result;
143
+#elif XCHAL_HAVE_S32C1I
111144 unsigned long tmp, result;
112145 __asm__ __volatile__(
113
- "1: l32i %1, %2, 0\n"
114
- " mov %0, %3\n"
115
- " wsr %1, scompare1\n"
116
- " s32c1i %0, %2, 0\n"
117
- " bne %0, %1, 1b\n"
118
- : "=&a" (result), "=&a" (tmp)
119
- : "a" (m), "a" (val)
146
+ "1: l32i %[tmp], %[mem]\n"
147
+ " mov %[result], %[val]\n"
148
+ " wsr %[tmp], scompare1\n"
149
+ " s32c1i %[result], %[mem]\n"
150
+ " bne %[result], %[tmp], 1b\n"
151
+ : [result] "=&a" (result), [tmp] "=&a" (tmp),
152
+ [mem] "+m" (*m)
153
+ : [val] "a" (val)
120154 : "memory"
121155 );
122156 return result;
....@@ -124,12 +158,12 @@
124158 unsigned long tmp;
125159 __asm__ __volatile__(
126160 " rsil a15, "__stringify(TOPLEVEL)"\n"
127
- " l32i %0, %1, 0\n"
128
- " s32i %2, %1, 0\n"
161
+ " l32i %[tmp], %[mem]\n"
162
+ " s32i %[val], %[mem]\n"
129163 " wsr a15, ps\n"
130164 " rsync\n"
131
- : "=&a" (tmp)
132
- : "a" (m), "a" (val)
165
+ : [tmp] "=&a" (tmp), [mem] "+m" (*m)
166
+ : [val] "a" (val)
133167 : "a15", "memory");
134168 return tmp;
135169 #endif
....@@ -137,6 +171,28 @@
137171
138172 #define xchg(ptr,x) \
139173 ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
174
+
175
+static inline u32 xchg_small(volatile void *ptr, u32 x, int size)
176
+{
177
+ int off = (unsigned long)ptr % sizeof(u32);
178
+ volatile u32 *p = ptr - off;
179
+#ifdef __BIG_ENDIAN
180
+ int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE;
181
+#else
182
+ int bitoff = off * BITS_PER_BYTE;
183
+#endif
184
+ u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff;
185
+ u32 oldv, newv;
186
+ u32 ret;
187
+
188
+ do {
189
+ oldv = READ_ONCE(*p);
190
+ ret = (oldv & bitmask) >> bitoff;
191
+ newv = (oldv & ~bitmask) | (x << bitoff);
192
+ } while (__cmpxchg_u32(p, oldv, newv) != oldv);
193
+
194
+ return ret;
195
+}
140196
141197 /*
142198 * This only works if the compiler isn't horribly bad at optimizing.
....@@ -150,11 +206,16 @@
150206 __xchg(unsigned long x, volatile void * ptr, int size)
151207 {
152208 switch (size) {
153
- case 4:
154
- return xchg_u32(ptr, x);
209
+ case 1:
210
+ return xchg_small(ptr, x, 1);
211
+ case 2:
212
+ return xchg_small(ptr, x, 2);
213
+ case 4:
214
+ return xchg_u32(ptr, x);
215
+ default:
216
+ __xchg_called_with_bad_pointer();
217
+ return x;
155218 }
156
- __xchg_called_with_bad_pointer();
157
- return x;
158219 }
159220
160221 #endif /* __ASSEMBLY__ */