xref: /openbmc/linux/arch/sparc/include/asm/spinlock_64.h (revision 8fa5723aa7e053d498336b48448b292fc2e0458b)
1 /* spinlock.h: 64-bit Sparc spinlock support.
2  *
3  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
4  */
5 
6 #ifndef __SPARC64_SPINLOCK_H
7 #define __SPARC64_SPINLOCK_H
8 
9 #ifndef __ASSEMBLY__
10 
11 /* To get debugging spinlocks which detect and catch
12  * deadlock situations, set CONFIG_DEBUG_SPINLOCK
13  * and rebuild your kernel.
14  */
15 
16 /* All of these locking primitives are expected to work properly
17  * even in an RMO memory model, which currently is what the kernel
18  * runs in.
19  *
20  * There is another issue.  Because we play games to save cycles
21  * in the non-contention case, we need to be extra careful about
22  * branch targets into the "spinning" code.  They live in their
23  * own section, but the newer V9 branches have a shorter range
24  * than the traditional 32-bit sparc branch variants.  The rule
25  * is that the branches that go into and out of the spinner sections
26  * must be pre-V9 branches.
27  */
28 
29 #define __raw_spin_is_locked(lp)	((lp)->lock != 0)
30 
31 #define __raw_spin_unlock_wait(lp)	\
32 	do {	rmb();			\
33 	} while((lp)->lock)
34 
35 static inline void __raw_spin_lock(raw_spinlock_t *lock)
36 {
37 	unsigned long tmp;
38 
39 	__asm__ __volatile__(
40 "1:	ldstub		[%1], %0\n"
41 "	membar		#StoreLoad | #StoreStore\n"
42 "	brnz,pn		%0, 2f\n"
43 "	 nop\n"
44 "	.subsection	2\n"
45 "2:	ldub		[%1], %0\n"
46 "	membar		#LoadLoad\n"
47 "	brnz,pt		%0, 2b\n"
48 "	 nop\n"
49 "	ba,a,pt		%%xcc, 1b\n"
50 "	.previous"
51 	: "=&r" (tmp)
52 	: "r" (lock)
53 	: "memory");
54 }
55 
56 static inline int __raw_spin_trylock(raw_spinlock_t *lock)
57 {
58 	unsigned long result;
59 
60 	__asm__ __volatile__(
61 "	ldstub		[%1], %0\n"
62 "	membar		#StoreLoad | #StoreStore"
63 	: "=r" (result)
64 	: "r" (lock)
65 	: "memory");
66 
67 	return (result == 0UL);
68 }
69 
70 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
71 {
72 	__asm__ __volatile__(
73 "	membar		#StoreStore | #LoadStore\n"
74 "	stb		%%g0, [%0]"
75 	: /* No outputs */
76 	: "r" (lock)
77 	: "memory");
78 }
79 
80 static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
81 {
82 	unsigned long tmp1, tmp2;
83 
84 	__asm__ __volatile__(
85 "1:	ldstub		[%2], %0\n"
86 "	membar		#StoreLoad | #StoreStore\n"
87 "	brnz,pn		%0, 2f\n"
88 "	 nop\n"
89 "	.subsection	2\n"
90 "2:	rdpr		%%pil, %1\n"
91 "	wrpr		%3, %%pil\n"
92 "3:	ldub		[%2], %0\n"
93 "	membar		#LoadLoad\n"
94 "	brnz,pt		%0, 3b\n"
95 "	 nop\n"
96 "	ba,pt		%%xcc, 1b\n"
97 "	 wrpr		%1, %%pil\n"
98 "	.previous"
99 	: "=&r" (tmp1), "=&r" (tmp2)
100 	: "r"(lock), "r"(flags)
101 	: "memory");
102 }
103 
104 /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
105 
106 static void inline __read_lock(raw_rwlock_t *lock)
107 {
108 	unsigned long tmp1, tmp2;
109 
110 	__asm__ __volatile__ (
111 "1:	ldsw		[%2], %0\n"
112 "	brlz,pn		%0, 2f\n"
113 "4:	 add		%0, 1, %1\n"
114 "	cas		[%2], %0, %1\n"
115 "	cmp		%0, %1\n"
116 "	membar		#StoreLoad | #StoreStore\n"
117 "	bne,pn		%%icc, 1b\n"
118 "	 nop\n"
119 "	.subsection	2\n"
120 "2:	ldsw		[%2], %0\n"
121 "	membar		#LoadLoad\n"
122 "	brlz,pt		%0, 2b\n"
123 "	 nop\n"
124 "	ba,a,pt		%%xcc, 4b\n"
125 "	.previous"
126 	: "=&r" (tmp1), "=&r" (tmp2)
127 	: "r" (lock)
128 	: "memory");
129 }
130 
131 static int inline __read_trylock(raw_rwlock_t *lock)
132 {
133 	int tmp1, tmp2;
134 
135 	__asm__ __volatile__ (
136 "1:	ldsw		[%2], %0\n"
137 "	brlz,a,pn	%0, 2f\n"
138 "	 mov		0, %0\n"
139 "	add		%0, 1, %1\n"
140 "	cas		[%2], %0, %1\n"
141 "	cmp		%0, %1\n"
142 "	membar		#StoreLoad | #StoreStore\n"
143 "	bne,pn		%%icc, 1b\n"
144 "	 mov		1, %0\n"
145 "2:"
146 	: "=&r" (tmp1), "=&r" (tmp2)
147 	: "r" (lock)
148 	: "memory");
149 
150 	return tmp1;
151 }
152 
153 static void inline __read_unlock(raw_rwlock_t *lock)
154 {
155 	unsigned long tmp1, tmp2;
156 
157 	__asm__ __volatile__(
158 "	membar	#StoreLoad | #LoadLoad\n"
159 "1:	lduw	[%2], %0\n"
160 "	sub	%0, 1, %1\n"
161 "	cas	[%2], %0, %1\n"
162 "	cmp	%0, %1\n"
163 "	bne,pn	%%xcc, 1b\n"
164 "	 nop"
165 	: "=&r" (tmp1), "=&r" (tmp2)
166 	: "r" (lock)
167 	: "memory");
168 }
169 
170 static void inline __write_lock(raw_rwlock_t *lock)
171 {
172 	unsigned long mask, tmp1, tmp2;
173 
174 	mask = 0x80000000UL;
175 
176 	__asm__ __volatile__(
177 "1:	lduw		[%2], %0\n"
178 "	brnz,pn		%0, 2f\n"
179 "4:	 or		%0, %3, %1\n"
180 "	cas		[%2], %0, %1\n"
181 "	cmp		%0, %1\n"
182 "	membar		#StoreLoad | #StoreStore\n"
183 "	bne,pn		%%icc, 1b\n"
184 "	 nop\n"
185 "	.subsection	2\n"
186 "2:	lduw		[%2], %0\n"
187 "	membar		#LoadLoad\n"
188 "	brnz,pt		%0, 2b\n"
189 "	 nop\n"
190 "	ba,a,pt		%%xcc, 4b\n"
191 "	.previous"
192 	: "=&r" (tmp1), "=&r" (tmp2)
193 	: "r" (lock), "r" (mask)
194 	: "memory");
195 }
196 
197 static void inline __write_unlock(raw_rwlock_t *lock)
198 {
199 	__asm__ __volatile__(
200 "	membar		#LoadStore | #StoreStore\n"
201 "	stw		%%g0, [%0]"
202 	: /* no outputs */
203 	: "r" (lock)
204 	: "memory");
205 }
206 
207 static int inline __write_trylock(raw_rwlock_t *lock)
208 {
209 	unsigned long mask, tmp1, tmp2, result;
210 
211 	mask = 0x80000000UL;
212 
213 	__asm__ __volatile__(
214 "	mov		0, %2\n"
215 "1:	lduw		[%3], %0\n"
216 "	brnz,pn		%0, 2f\n"
217 "	 or		%0, %4, %1\n"
218 "	cas		[%3], %0, %1\n"
219 "	cmp		%0, %1\n"
220 "	membar		#StoreLoad | #StoreStore\n"
221 "	bne,pn		%%icc, 1b\n"
222 "	 nop\n"
223 "	mov		1, %2\n"
224 "2:"
225 	: "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
226 	: "r" (lock), "r" (mask)
227 	: "memory");
228 
229 	return result;
230 }
231 
232 #define __raw_read_lock(p)	__read_lock(p)
233 #define __raw_read_trylock(p)	__read_trylock(p)
234 #define __raw_read_unlock(p)	__read_unlock(p)
235 #define __raw_write_lock(p)	__write_lock(p)
236 #define __raw_write_unlock(p)	__write_unlock(p)
237 #define __raw_write_trylock(p)	__write_trylock(p)
238 
239 #define __raw_read_can_lock(rw)		(!((rw)->lock & 0x80000000UL))
240 #define __raw_write_can_lock(rw)	(!(rw)->lock)
241 
242 #define _raw_spin_relax(lock)	cpu_relax()
243 #define _raw_read_relax(lock)	cpu_relax()
244 #define _raw_write_relax(lock)	cpu_relax()
245 
246 #endif /* !(__ASSEMBLY__) */
247 
248 #endif /* !(__SPARC64_SPINLOCK_H) */
249