xref: /illumos-gate/usr/src/uts/intel/ml/lock_prim.S (revision 5d9d9091f564c198a760790b0bfa72c44e17912b)
1*5d9d9091SRichard Lowe/*
2*5d9d9091SRichard Lowe * CDDL HEADER START
3*5d9d9091SRichard Lowe *
4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the
5*5d9d9091SRichard Lowe * Common Development and Distribution License (the "License").
6*5d9d9091SRichard Lowe * You may not use this file except in compliance with the License.
7*5d9d9091SRichard Lowe *
8*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*5d9d9091SRichard Lowe * See the License for the specific language governing permissions
11*5d9d9091SRichard Lowe * and limitations under the License.
12*5d9d9091SRichard Lowe *
13*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*5d9d9091SRichard Lowe *
19*5d9d9091SRichard Lowe * CDDL HEADER END
20*5d9d9091SRichard Lowe */
21*5d9d9091SRichard Lowe/*
22*5d9d9091SRichard Lowe * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*5d9d9091SRichard Lowe * Use is subject to license terms.
24*5d9d9091SRichard Lowe */
25*5d9d9091SRichard Lowe
26*5d9d9091SRichard Lowe/*
27*5d9d9091SRichard Lowe * Copyright 2019 Joyent, Inc.
28*5d9d9091SRichard Lowe * Copyright 2022 Oxide Computer Company
29*5d9d9091SRichard Lowe */
30*5d9d9091SRichard Lowe
31*5d9d9091SRichard Lowe#include "assym.h"
32*5d9d9091SRichard Lowe
33*5d9d9091SRichard Lowe#include <sys/mutex_impl.h>
34*5d9d9091SRichard Lowe#include <sys/asm_linkage.h>
35*5d9d9091SRichard Lowe#include <sys/asm_misc.h>
36*5d9d9091SRichard Lowe#include <sys/regset.h>
37*5d9d9091SRichard Lowe#include <sys/rwlock_impl.h>
38*5d9d9091SRichard Lowe#include <sys/lockstat.h>
39*5d9d9091SRichard Lowe
40*5d9d9091SRichard Lowe
41*5d9d9091SRichard Lowe#if defined(OPTERON_ERRATUM_147)
42*5d9d9091SRichard Lowe
43*5d9d9091SRichard Lowe/*
44*5d9d9091SRichard Lowe * Leave space for an lfence to be inserted if required by a CPU which suffers
45*5d9d9091SRichard Lowe * from this erratum.  Pad (with nops) the location for the lfence so that it
46*5d9d9091SRichard Lowe * is adequately aligned for atomic hotpatching.
47*5d9d9091SRichard Lowe */
48*5d9d9091SRichard Lowe#define	ERRATUM147_PATCH_POINT(name)	\
49*5d9d9091SRichard Lowe	.align	4, NOP_INSTR;		\
50*5d9d9091SRichard Lowe.##name##_147_patch_point:		\
51*5d9d9091SRichard Lowe	nop;				\
52*5d9d9091SRichard Lowe	nop;				\
53*5d9d9091SRichard Lowe	nop;				\
54*5d9d9091SRichard Lowe	nop;
55*5d9d9091SRichard Lowe
56*5d9d9091SRichard Lowe#else /* defined(OPTERON_ERRATUM_147) */
57*5d9d9091SRichard Lowe
58*5d9d9091SRichard Lowe/* Empty macro so ifdefs are not required for all of the erratum sites. */
59*5d9d9091SRichard Lowe#define	ERRATUM147_PATCH_POINT(name)
60*5d9d9091SRichard Lowe
61*5d9d9091SRichard Lowe#endif /* defined(OPTERON_ERRATUM_147) */
62*5d9d9091SRichard Lowe
63*5d9d9091SRichard Lowe/*
64*5d9d9091SRichard Lowe * Patch point for lockstat probes.  When the associated probe is disabled, it
65*5d9d9091SRichard Lowe * will 'ret' from the function.  It is hotpatched to allow execution to fall
66*5d9d9091SRichard Lowe * through when the probe is enabled.
67*5d9d9091SRichard Lowe */
68*5d9d9091SRichard Lowe#define	LOCKSTAT_RET(name)		\
69*5d9d9091SRichard Lowe.##name##_lockstat_patch_point:	\
70*5d9d9091SRichard Lowe	ret;
71*5d9d9091SRichard Lowe
72*5d9d9091SRichard Lowe/*
73*5d9d9091SRichard Lowe * lock_try(lp), ulock_try(lp)
74*5d9d9091SRichard Lowe *	- returns non-zero on success.
75*5d9d9091SRichard Lowe *	- doesn't block interrupts so don't use this to spin on a lock.
76*5d9d9091SRichard Lowe *
77*5d9d9091SRichard Lowe * ulock_try() is for a lock in the user address space.
78*5d9d9091SRichard Lowe */
79*5d9d9091SRichard Lowe
80*5d9d9091SRichard Lowe	.globl	kernelbase
81*5d9d9091SRichard Lowe
82*5d9d9091SRichard Lowe	ENTRY(lock_try)
83*5d9d9091SRichard Lowe	movb	$-1, %dl
84*5d9d9091SRichard Lowe	movzbq	%dl, %rax
85*5d9d9091SRichard Lowe	xchgb	%dl, (%rdi)
86*5d9d9091SRichard Lowe	xorb	%dl, %al
87*5d9d9091SRichard Lowe	LOCKSTAT_RET(lock_try)
88*5d9d9091SRichard Lowe
89*5d9d9091SRichard Lowe	testb	%al, %al
90*5d9d9091SRichard Lowe	jnz	0f
91*5d9d9091SRichard Lowe	ret
92*5d9d9091SRichard Lowe0:
93*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx	/* rdx = thread addr */
94*5d9d9091SRichard Lowe	movq	%rdi, %rsi		/* rsi = lock addr */
95*5d9d9091SRichard Lowe	movl	$LS_LOCK_TRY_ACQUIRE, %edi /* edi = event */
96*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
97*5d9d9091SRichard Lowe	SET_SIZE(lock_try)
98*5d9d9091SRichard Lowe
99*5d9d9091SRichard Lowe	ENTRY(lock_spin_try)
100*5d9d9091SRichard Lowe	movb	$-1, %dl
101*5d9d9091SRichard Lowe	movzbq	%dl, %rax
102*5d9d9091SRichard Lowe	xchgb	%dl, (%rdi)
103*5d9d9091SRichard Lowe	xorb	%dl, %al
104*5d9d9091SRichard Lowe	ret
105*5d9d9091SRichard Lowe	SET_SIZE(lock_spin_try)
106*5d9d9091SRichard Lowe
107*5d9d9091SRichard Lowe	ENTRY(ulock_try)
108*5d9d9091SRichard Lowe#ifdef DEBUG
109*5d9d9091SRichard Lowe	movq	kernelbase(%rip), %rax
110*5d9d9091SRichard Lowe	cmpq	%rax, %rdi		/* test uaddr < kernelbase */
111*5d9d9091SRichard Lowe	jb	ulock_pass		/*	uaddr < kernelbase, proceed */
112*5d9d9091SRichard Lowe
113*5d9d9091SRichard Lowe	movq	%rdi, %r12		/* preserve lock ptr for debugging */
114*5d9d9091SRichard Lowe	leaq	.ulock_panic_msg(%rip), %rdi
115*5d9d9091SRichard Lowe	pushq	%rbp
116*5d9d9091SRichard Lowe	movq	%rsp, %rbp
117*5d9d9091SRichard Lowe	xorl	%eax, %eax		/* clear for varargs */
118*5d9d9091SRichard Lowe	call	panic
119*5d9d9091SRichard Lowe
120*5d9d9091SRichard Lowe#endif /* DEBUG */
121*5d9d9091SRichard Lowe
122*5d9d9091SRichard Loweulock_pass:
123*5d9d9091SRichard Lowe	movl	$1, %eax
124*5d9d9091SRichard Lowe	xchgb	%al, (%rdi)
125*5d9d9091SRichard Lowe	xorb	$1, %al
126*5d9d9091SRichard Lowe	ret
127*5d9d9091SRichard Lowe	SET_SIZE(ulock_try)
128*5d9d9091SRichard Lowe
129*5d9d9091SRichard Lowe#ifdef DEBUG
130*5d9d9091SRichard Lowe	.data
131*5d9d9091SRichard Lowe.ulock_panic_msg:
132*5d9d9091SRichard Lowe	.string "ulock_try: Argument is above kernelbase"
133*5d9d9091SRichard Lowe	.text
134*5d9d9091SRichard Lowe#endif	/* DEBUG */
135*5d9d9091SRichard Lowe
136*5d9d9091SRichard Lowe/*
137*5d9d9091SRichard Lowe * lock_clear(lp)
138*5d9d9091SRichard Lowe *	- unlock lock without changing interrupt priority level.
139*5d9d9091SRichard Lowe */
140*5d9d9091SRichard Lowe
141*5d9d9091SRichard Lowe	ENTRY(lock_clear)
142*5d9d9091SRichard Lowe	movb	$0, (%rdi)
143*5d9d9091SRichard Lowe	LOCKSTAT_RET(lock_clear)
144*5d9d9091SRichard Lowe
145*5d9d9091SRichard Lowe	movq	%rdi, %rsi			/* rsi = lock addr */
146*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx		/* rdx = thread addr */
147*5d9d9091SRichard Lowe	movl	$LS_LOCK_CLEAR_RELEASE, %edi	/* edi = event */
148*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
149*5d9d9091SRichard Lowe	SET_SIZE(lock_clear)
150*5d9d9091SRichard Lowe
151*5d9d9091SRichard Lowe	ENTRY(ulock_clear)
152*5d9d9091SRichard Lowe#ifdef DEBUG
153*5d9d9091SRichard Lowe	movq	kernelbase(%rip), %rcx
154*5d9d9091SRichard Lowe	cmpq	%rcx, %rdi		/* test uaddr < kernelbase */
155*5d9d9091SRichard Lowe	jb	ulock_clr		/*	 uaddr < kernelbase, proceed */
156*5d9d9091SRichard Lowe
157*5d9d9091SRichard Lowe	leaq	.ulock_clear_msg(%rip), %rdi
158*5d9d9091SRichard Lowe	pushq	%rbp
159*5d9d9091SRichard Lowe	movq	%rsp, %rbp
160*5d9d9091SRichard Lowe	xorl	%eax, %eax		/* clear for varargs */
161*5d9d9091SRichard Lowe	call	panic
162*5d9d9091SRichard Lowe#endif
163*5d9d9091SRichard Lowe
164*5d9d9091SRichard Loweulock_clr:
165*5d9d9091SRichard Lowe	movb	$0, (%rdi)
166*5d9d9091SRichard Lowe	ret
167*5d9d9091SRichard Lowe	SET_SIZE(ulock_clear)
168*5d9d9091SRichard Lowe
169*5d9d9091SRichard Lowe#ifdef DEBUG
170*5d9d9091SRichard Lowe	.data
171*5d9d9091SRichard Lowe.ulock_clear_msg:
172*5d9d9091SRichard Lowe	.string "ulock_clear: Argument is above kernelbase"
173*5d9d9091SRichard Lowe	.text
174*5d9d9091SRichard Lowe#endif	/* DEBUG */
175*5d9d9091SRichard Lowe
176*5d9d9091SRichard Lowe
177*5d9d9091SRichard Lowe/*
178*5d9d9091SRichard Lowe * lock_set_spl(lock_t *lp, int new_pil, u_short *old_pil)
179*5d9d9091SRichard Lowe * Drops lp, sets pil to new_pil, stores old pil in *old_pil.
180*5d9d9091SRichard Lowe */
181*5d9d9091SRichard Lowe
182*5d9d9091SRichard Lowe	ENTRY(lock_set_spl)
183*5d9d9091SRichard Lowe	pushq	%rbp
184*5d9d9091SRichard Lowe	movq	%rsp, %rbp
185*5d9d9091SRichard Lowe	subq	$32, %rsp
186*5d9d9091SRichard Lowe	movl	%esi, 8(%rsp)		/* save priority level */
187*5d9d9091SRichard Lowe	movq	%rdx, 16(%rsp)		/* save old pil ptr */
188*5d9d9091SRichard Lowe	movq	%rdi, 24(%rsp)		/* save lock pointer */
189*5d9d9091SRichard Lowe	movl	%esi, %edi		/* pass priority level */
190*5d9d9091SRichard Lowe	call	splr			/* raise priority level */
191*5d9d9091SRichard Lowe	movq	24(%rsp), %rdi		/* rdi = lock addr */
192*5d9d9091SRichard Lowe	movb	$-1, %dl
193*5d9d9091SRichard Lowe	xchgb	%dl, (%rdi)		/* try to set lock */
194*5d9d9091SRichard Lowe	testb	%dl, %dl		/* did we get the lock? ... */
195*5d9d9091SRichard Lowe	jnz	.lss_miss		/* ... no, go to C for the hard case */
196*5d9d9091SRichard Lowe	movq	16(%rsp), %rdx		/* rdx = old pil addr */
197*5d9d9091SRichard Lowe	movw	%ax, (%rdx)		/* store old pil */
198*5d9d9091SRichard Lowe	leave
199*5d9d9091SRichard Lowe	LOCKSTAT_RET(lock_set_spl)
200*5d9d9091SRichard Lowe
201*5d9d9091SRichard Lowe	movq	%rdi, %rsi		/* rsi = lock addr */
202*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx	/* rdx = thread addr */
203*5d9d9091SRichard Lowe	movl	$LS_LOCK_SET_SPL_ACQUIRE, %edi
204*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
205*5d9d9091SRichard Lowe
206*5d9d9091SRichard Lowe.lss_miss:
207*5d9d9091SRichard Lowe	movl	8(%rsp), %esi		/* new_pil */
208*5d9d9091SRichard Lowe	movq	16(%rsp), %rdx		/* old_pil_addr */
209*5d9d9091SRichard Lowe	movl	%eax, %ecx		/* original pil */
210*5d9d9091SRichard Lowe	leave				/* unwind stack */
211*5d9d9091SRichard Lowe	jmp	lock_set_spl_spin
212*5d9d9091SRichard Lowe	SET_SIZE(lock_set_spl)
213*5d9d9091SRichard Lowe
214*5d9d9091SRichard Lowe/*
215*5d9d9091SRichard Lowe * void
216*5d9d9091SRichard Lowe * lock_init(lp)
217*5d9d9091SRichard Lowe */
218*5d9d9091SRichard Lowe
219*5d9d9091SRichard Lowe	ENTRY(lock_init)
220*5d9d9091SRichard Lowe	movb	$0, (%rdi)
221*5d9d9091SRichard Lowe	ret
222*5d9d9091SRichard Lowe	SET_SIZE(lock_init)
223*5d9d9091SRichard Lowe
224*5d9d9091SRichard Lowe/*
225*5d9d9091SRichard Lowe * void
226*5d9d9091SRichard Lowe * lock_set(lp)
227*5d9d9091SRichard Lowe */
228*5d9d9091SRichard Lowe
229*5d9d9091SRichard Lowe	ENTRY(lock_set)
230*5d9d9091SRichard Lowe	movb	$-1, %dl
231*5d9d9091SRichard Lowe	xchgb	%dl, (%rdi)		/* try to set lock */
232*5d9d9091SRichard Lowe	testb	%dl, %dl		/* did we get it? */
233*5d9d9091SRichard Lowe	jnz	lock_set_spin		/* no, go to C for the hard case */
234*5d9d9091SRichard Lowe	LOCKSTAT_RET(lock_set)
235*5d9d9091SRichard Lowe
236*5d9d9091SRichard Lowe	movq	%rdi, %rsi		/* rsi = lock addr */
237*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx	/* rdx = thread addr */
238*5d9d9091SRichard Lowe	movl	$LS_LOCK_SET_ACQUIRE, %edi
239*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
240*5d9d9091SRichard Lowe	SET_SIZE(lock_set)
241*5d9d9091SRichard Lowe
242*5d9d9091SRichard Lowe/*
243*5d9d9091SRichard Lowe * lock_clear_splx(lp, s)
244*5d9d9091SRichard Lowe */
245*5d9d9091SRichard Lowe
246*5d9d9091SRichard Lowe	ENTRY(lock_clear_splx)
247*5d9d9091SRichard Lowe	pushq	%rbp
248*5d9d9091SRichard Lowe	movq	%rsp, %rbp
249*5d9d9091SRichard Lowe	pushq	%rdi		/* save lp across call for lockstat */
250*5d9d9091SRichard Lowe	movb	$0, (%rdi)	/* clear lock */
251*5d9d9091SRichard Lowe	movl	%esi, %edi	/* arg for splx */
252*5d9d9091SRichard Lowe	call	splx		/* let splx do its thing */
253*5d9d9091SRichard Lowe	popq	%rsi		/* retreive lp for lockstat */
254*5d9d9091SRichard Lowe	leave
255*5d9d9091SRichard Lowe	LOCKSTAT_RET(lock_clear_splx)
256*5d9d9091SRichard Lowe
257*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx	/* rdx = thread addr */
258*5d9d9091SRichard Lowe	movl	$LS_LOCK_CLEAR_SPLX_RELEASE, %edi
259*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
260*5d9d9091SRichard Lowe	SET_SIZE(lock_clear_splx)
261*5d9d9091SRichard Lowe
262*5d9d9091SRichard Lowe/*
263*5d9d9091SRichard Lowe * mutex_enter() and mutex_exit().
264*5d9d9091SRichard Lowe *
265*5d9d9091SRichard Lowe * These routines handle the simple cases of mutex_enter() (adaptive
266*5d9d9091SRichard Lowe * lock, not held) and mutex_exit() (adaptive lock, held, no waiters).
267*5d9d9091SRichard Lowe * If anything complicated is going on we punt to mutex_vector_enter().
268*5d9d9091SRichard Lowe *
269*5d9d9091SRichard Lowe * mutex_tryenter() is similar to mutex_enter() but returns zero if
270*5d9d9091SRichard Lowe * the lock cannot be acquired, nonzero on success.
271*5d9d9091SRichard Lowe *
272*5d9d9091SRichard Lowe * If mutex_exit() gets preempted in the window between checking waiters
273*5d9d9091SRichard Lowe * and clearing the lock, we can miss wakeups.  Disabling preemption
274*5d9d9091SRichard Lowe * in the mutex code is prohibitively expensive, so instead we detect
275*5d9d9091SRichard Lowe * mutex preemption by examining the trapped PC in the interrupt path.
276*5d9d9091SRichard Lowe * If we interrupt a thread in mutex_exit() that has not yet cleared
277*5d9d9091SRichard Lowe * the lock, cmnint() resets its PC back to the beginning of
278*5d9d9091SRichard Lowe * mutex_exit() so it will check again for waiters when it resumes.
279*5d9d9091SRichard Lowe */
280*5d9d9091SRichard Lowe
281*5d9d9091SRichard Lowe	ENTRY_NP(mutex_enter)
282*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx		/* rdx = thread ptr */
283*5d9d9091SRichard Lowe	xorl	%eax, %eax			/* rax = 0 (unheld adaptive) */
284*5d9d9091SRichard Lowe	lock
285*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)
286*5d9d9091SRichard Lowe	jnz	mutex_vector_enter
287*5d9d9091SRichard Lowe
288*5d9d9091SRichard Lowe	ERRATUM147_PATCH_POINT(mutex_enter)
289*5d9d9091SRichard Lowe
290*5d9d9091SRichard Lowe	LOCKSTAT_RET(mutex_enter)
291*5d9d9091SRichard Lowe
292*5d9d9091SRichard Lowe	movq	%rdi, %rsi
293*5d9d9091SRichard Lowe	movl	$LS_MUTEX_ENTER_ACQUIRE, %edi
294*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
295*5d9d9091SRichard Lowe	SET_SIZE(mutex_enter)
296*5d9d9091SRichard Lowe
297*5d9d9091SRichard Lowe
298*5d9d9091SRichard Lowe/*
299*5d9d9091SRichard Lowe * expects %rdx=thread, %rsi=lock, %edi=lockstat event
300*5d9d9091SRichard Lowe */
301*5d9d9091SRichard Lowe	ENTRY_NP(lockstat_wrapper)
302*5d9d9091SRichard Lowe	incb	T_LOCKSTAT(%rdx)		/* curthread->t_lockstat++ */
303*5d9d9091SRichard Lowe	leaq	lockstat_probemap(%rip), %rax
304*5d9d9091SRichard Lowe	movl	(%rax, %rdi, DTRACE_IDSIZE), %eax
305*5d9d9091SRichard Lowe	testl	%eax, %eax			/* check for non-zero probe */
306*5d9d9091SRichard Lowe	jz	1f
307*5d9d9091SRichard Lowe	pushq	%rbp
308*5d9d9091SRichard Lowe	movq	%rsp, %rbp
309*5d9d9091SRichard Lowe	movl	%eax, %edi
310*5d9d9091SRichard Lowe	movq	lockstat_probe, %rax
311*5d9d9091SRichard Lowe	INDIRECT_CALL_REG(rax)
312*5d9d9091SRichard Lowe	leave					/* unwind stack */
313*5d9d9091SRichard Lowe1:
314*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx		/* reload thread ptr */
315*5d9d9091SRichard Lowe	decb	T_LOCKSTAT(%rdx)		/* curthread->t_lockstat-- */
316*5d9d9091SRichard Lowe	movl	$1, %eax			/* return success if tryenter */
317*5d9d9091SRichard Lowe	ret
318*5d9d9091SRichard Lowe	SET_SIZE(lockstat_wrapper)
319*5d9d9091SRichard Lowe
320*5d9d9091SRichard Lowe/*
321*5d9d9091SRichard Lowe * expects %rcx=thread, %rdx=arg, %rsi=lock, %edi=lockstat event
322*5d9d9091SRichard Lowe */
323*5d9d9091SRichard Lowe	ENTRY(lockstat_wrapper_arg)
324*5d9d9091SRichard Lowe	incb	T_LOCKSTAT(%rcx)		/* curthread->t_lockstat++ */
325*5d9d9091SRichard Lowe	leaq	lockstat_probemap(%rip), %rax
326*5d9d9091SRichard Lowe	movl	(%rax, %rdi, DTRACE_IDSIZE), %eax
327*5d9d9091SRichard Lowe	testl	%eax, %eax			/* check for non-zero probe */
328*5d9d9091SRichard Lowe	jz	1f
329*5d9d9091SRichard Lowe	pushq	%rbp
330*5d9d9091SRichard Lowe	movq	%rsp, %rbp
331*5d9d9091SRichard Lowe	movl	%eax, %edi
332*5d9d9091SRichard Lowe	movq	lockstat_probe, %rax
333*5d9d9091SRichard Lowe	INDIRECT_CALL_REG(rax)
334*5d9d9091SRichard Lowe	leave					/* unwind stack */
335*5d9d9091SRichard Lowe1:
336*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx		/* reload thread ptr */
337*5d9d9091SRichard Lowe	decb	T_LOCKSTAT(%rdx)		/* curthread->t_lockstat-- */
338*5d9d9091SRichard Lowe	movl	$1, %eax			/* return success if tryenter */
339*5d9d9091SRichard Lowe	ret
340*5d9d9091SRichard Lowe	SET_SIZE(lockstat_wrapper_arg)
341*5d9d9091SRichard Lowe
342*5d9d9091SRichard Lowe
343*5d9d9091SRichard Lowe	ENTRY(mutex_tryenter)
344*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx		/* rdx = thread ptr */
345*5d9d9091SRichard Lowe	xorl	%eax, %eax			/* rax = 0 (unheld adaptive) */
346*5d9d9091SRichard Lowe	lock
347*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)
348*5d9d9091SRichard Lowe	jnz	mutex_vector_tryenter
349*5d9d9091SRichard Lowe	not	%eax				/* return success (nonzero) */
350*5d9d9091SRichard Lowe
351*5d9d9091SRichard Lowe	ERRATUM147_PATCH_POINT(mutex_tryenter)
352*5d9d9091SRichard Lowe
353*5d9d9091SRichard Lowe	LOCKSTAT_RET(mutex_tryenter)
354*5d9d9091SRichard Lowe
355*5d9d9091SRichard Lowe	movq	%rdi, %rsi
356*5d9d9091SRichard Lowe	movl	$LS_MUTEX_TRYENTER_ACQUIRE, %edi
357*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
358*5d9d9091SRichard Lowe	SET_SIZE(mutex_tryenter)
359*5d9d9091SRichard Lowe
360*5d9d9091SRichard Lowe	ENTRY(mutex_adaptive_tryenter)
361*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx		/* rdx = thread ptr */
362*5d9d9091SRichard Lowe	xorl	%eax, %eax			/* rax = 0 (unheld adaptive) */
363*5d9d9091SRichard Lowe	lock
364*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)
365*5d9d9091SRichard Lowe	jnz	0f
366*5d9d9091SRichard Lowe	not	%eax				/* return success (nonzero) */
367*5d9d9091SRichard Lowe
368*5d9d9091SRichard Lowe	ERRATUM147_PATCH_POINT(mutex_atryenter)
369*5d9d9091SRichard Lowe
370*5d9d9091SRichard Lowe	ret
371*5d9d9091SRichard Lowe0:
372*5d9d9091SRichard Lowe	xorl	%eax, %eax			/* return failure */
373*5d9d9091SRichard Lowe	ret
374*5d9d9091SRichard Lowe	SET_SIZE(mutex_adaptive_tryenter)
375*5d9d9091SRichard Lowe
376*5d9d9091SRichard Lowe	.globl	mutex_owner_running_critical_start
377*5d9d9091SRichard Lowe
378*5d9d9091SRichard Lowe	ENTRY(mutex_owner_running)
379*5d9d9091SRichard Lowemutex_owner_running_critical_start:
380*5d9d9091SRichard Lowe	movq	(%rdi), %r11		/* get owner field */
381*5d9d9091SRichard Lowe	andq	$MUTEX_THREAD, %r11	/* remove waiters bit */
382*5d9d9091SRichard Lowe	cmpq	$0, %r11		/* if free, skip */
383*5d9d9091SRichard Lowe	je	1f			/* go return 0 */
384*5d9d9091SRichard Lowe	movq	T_CPU(%r11), %r8	/* get owner->t_cpu */
385*5d9d9091SRichard Lowe	movq	CPU_THREAD(%r8), %r9	/* get t_cpu->cpu_thread */
386*5d9d9091SRichard Lowe.mutex_owner_running_critical_end:
387*5d9d9091SRichard Lowe	cmpq	%r11, %r9	/* owner == running thread? */
388*5d9d9091SRichard Lowe	je	2f		/* yes, go return cpu */
389*5d9d9091SRichard Lowe1:
390*5d9d9091SRichard Lowe	xorq	%rax, %rax	/* return 0 */
391*5d9d9091SRichard Lowe	ret
392*5d9d9091SRichard Lowe2:
393*5d9d9091SRichard Lowe	movq	%r8, %rax		/* return cpu */
394*5d9d9091SRichard Lowe	ret
395*5d9d9091SRichard Lowe	SET_SIZE(mutex_owner_running)
396*5d9d9091SRichard Lowe
397*5d9d9091SRichard Lowe	.globl	mutex_owner_running_critical_size
398*5d9d9091SRichard Lowe	.type	mutex_owner_running_critical_size, @object
399*5d9d9091SRichard Lowe	.align	CPTRSIZE
400*5d9d9091SRichard Lowemutex_owner_running_critical_size:
401*5d9d9091SRichard Lowe	.quad	.mutex_owner_running_critical_end - mutex_owner_running_critical_start
402*5d9d9091SRichard Lowe	SET_SIZE(mutex_owner_running_critical_size)
403*5d9d9091SRichard Lowe
404*5d9d9091SRichard Lowe	.globl	mutex_exit_critical_start
405*5d9d9091SRichard Lowe
406*5d9d9091SRichard Lowe	ENTRY(mutex_exit)
407*5d9d9091SRichard Lowemutex_exit_critical_start:		/* If interrupted, restart here */
408*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx
409*5d9d9091SRichard Lowe	cmpq	%rdx, (%rdi)
410*5d9d9091SRichard Lowe	jne	mutex_vector_exit		/* wrong type or wrong owner */
411*5d9d9091SRichard Lowe	movq	$0, (%rdi)			/* clear owner AND lock */
412*5d9d9091SRichard Lowe.mutex_exit_critical_end:
413*5d9d9091SRichard Lowe	LOCKSTAT_RET(mutex_exit)
414*5d9d9091SRichard Lowe
415*5d9d9091SRichard Lowe	movq	%rdi, %rsi
416*5d9d9091SRichard Lowe	movl	$LS_MUTEX_EXIT_RELEASE, %edi
417*5d9d9091SRichard Lowe	jmp	lockstat_wrapper
418*5d9d9091SRichard Lowe	SET_SIZE(mutex_exit)
419*5d9d9091SRichard Lowe
420*5d9d9091SRichard Lowe	.globl	mutex_exit_critical_size
421*5d9d9091SRichard Lowe	.type	mutex_exit_critical_size, @object
422*5d9d9091SRichard Lowe	.align	CPTRSIZE
423*5d9d9091SRichard Lowemutex_exit_critical_size:
424*5d9d9091SRichard Lowe	.quad	.mutex_exit_critical_end - mutex_exit_critical_start
425*5d9d9091SRichard Lowe	SET_SIZE(mutex_exit_critical_size)
426*5d9d9091SRichard Lowe
427*5d9d9091SRichard Lowe/*
428*5d9d9091SRichard Lowe * rw_enter() and rw_exit().
429*5d9d9091SRichard Lowe *
430*5d9d9091SRichard Lowe * These routines handle the simple cases of rw_enter (write-locking an unheld
431*5d9d9091SRichard Lowe * lock or read-locking a lock that's neither write-locked nor write-wanted)
432*5d9d9091SRichard Lowe * and rw_exit (no waiters or not the last reader).  If anything complicated
433*5d9d9091SRichard Lowe * is going on we punt to rw_enter_sleep() and rw_exit_wakeup(), respectively.
434*5d9d9091SRichard Lowe */
435*5d9d9091SRichard Lowe
436*5d9d9091SRichard Lowe	ENTRY(rw_enter)
437*5d9d9091SRichard Lowe	cmpl	$RW_WRITER, %esi
438*5d9d9091SRichard Lowe	je	.rw_write_enter
439*5d9d9091SRichard Lowe	movq	(%rdi), %rax			/* rax = old rw_wwwh value */
440*5d9d9091SRichard Lowe	testl	$RW_WRITE_LOCKED|RW_WRITE_WANTED, %eax
441*5d9d9091SRichard Lowe	jnz	rw_enter_sleep
442*5d9d9091SRichard Lowe	leaq	RW_READ_LOCK(%rax), %rdx	/* rdx = new rw_wwwh value */
443*5d9d9091SRichard Lowe	lock
444*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)			/* try to grab read lock */
445*5d9d9091SRichard Lowe	jnz	rw_enter_sleep
446*5d9d9091SRichard Lowe	LOCKSTAT_RET(rw_read_enter)
447*5d9d9091SRichard Lowe
448*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rcx		/* rcx = thread ptr */
449*5d9d9091SRichard Lowe	movq	%rdi, %rsi			/* rsi = lock ptr */
450*5d9d9091SRichard Lowe	movl	$LS_RW_ENTER_ACQUIRE, %edi
451*5d9d9091SRichard Lowe	movl	$RW_READER, %edx
452*5d9d9091SRichard Lowe	jmp	lockstat_wrapper_arg
453*5d9d9091SRichard Lowe
454*5d9d9091SRichard Lowe.rw_write_enter:
455*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rdx
456*5d9d9091SRichard Lowe	orq	$RW_WRITE_LOCKED, %rdx		/* rdx = write-locked value */
457*5d9d9091SRichard Lowe	xorl	%eax, %eax			/* rax = unheld value */
458*5d9d9091SRichard Lowe	lock
459*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)			/* try to grab write lock */
460*5d9d9091SRichard Lowe	jnz	rw_enter_sleep
461*5d9d9091SRichard Lowe
462*5d9d9091SRichard Lowe	ERRATUM147_PATCH_POINT(rw_write_enter)
463*5d9d9091SRichard Lowe
464*5d9d9091SRichard Lowe	LOCKSTAT_RET(rw_write_enter)
465*5d9d9091SRichard Lowe
466*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rcx		/* rcx = thread ptr */
467*5d9d9091SRichard Lowe	movq	%rdi, %rsi			/* rsi = lock ptr */
468*5d9d9091SRichard Lowe	movl	$LS_RW_ENTER_ACQUIRE, %edi
469*5d9d9091SRichard Lowe	movl	$RW_WRITER, %edx
470*5d9d9091SRichard Lowe	jmp	lockstat_wrapper_arg
471*5d9d9091SRichard Lowe	SET_SIZE(rw_enter)
472*5d9d9091SRichard Lowe
473*5d9d9091SRichard Lowe	ENTRY(rw_exit)
474*5d9d9091SRichard Lowe	movq	(%rdi), %rax			/* rax = old rw_wwwh value */
475*5d9d9091SRichard Lowe	cmpl	$RW_READ_LOCK, %eax		/* single-reader, no waiters? */
476*5d9d9091SRichard Lowe	jne	.rw_not_single_reader
477*5d9d9091SRichard Lowe	xorl	%edx, %edx			/* rdx = new value (unheld) */
478*5d9d9091SRichard Lowe.rw_read_exit:
479*5d9d9091SRichard Lowe	lock
480*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)			/* try to drop read lock */
481*5d9d9091SRichard Lowe	jnz	rw_exit_wakeup
482*5d9d9091SRichard Lowe	LOCKSTAT_RET(rw_read_exit)
483*5d9d9091SRichard Lowe
484*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rcx		/* rcx = thread ptr */
485*5d9d9091SRichard Lowe	movq	%rdi, %rsi			/* rsi = lock ptr */
486*5d9d9091SRichard Lowe	movl	$LS_RW_EXIT_RELEASE, %edi
487*5d9d9091SRichard Lowe	movl	$RW_READER, %edx
488*5d9d9091SRichard Lowe	jmp	lockstat_wrapper_arg
489*5d9d9091SRichard Lowe
490*5d9d9091SRichard Lowe.rw_not_single_reader:
491*5d9d9091SRichard Lowe	testl	$RW_WRITE_LOCKED, %eax	/* write-locked or write-wanted? */
492*5d9d9091SRichard Lowe	jnz	.rw_write_exit
493*5d9d9091SRichard Lowe	leaq	-RW_READ_LOCK(%rax), %rdx	/* rdx = new value */
494*5d9d9091SRichard Lowe	cmpl	$RW_READ_LOCK, %edx
495*5d9d9091SRichard Lowe	jge	.rw_read_exit		/* not last reader, safe to drop */
496*5d9d9091SRichard Lowe	jmp	rw_exit_wakeup			/* last reader with waiters */
497*5d9d9091SRichard Lowe.rw_write_exit:
498*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rax		/* rax = thread ptr */
499*5d9d9091SRichard Lowe	xorl	%edx, %edx			/* rdx = new value (unheld) */
500*5d9d9091SRichard Lowe	orq	$RW_WRITE_LOCKED, %rax		/* eax = write-locked value */
501*5d9d9091SRichard Lowe	lock
502*5d9d9091SRichard Lowe	cmpxchgq %rdx, (%rdi)			/* try to drop read lock */
503*5d9d9091SRichard Lowe	jnz	rw_exit_wakeup
504*5d9d9091SRichard Lowe	LOCKSTAT_RET(rw_write_exit)
505*5d9d9091SRichard Lowe
506*5d9d9091SRichard Lowe	movq	%gs:CPU_THREAD, %rcx		/* rcx = thread ptr */
507*5d9d9091SRichard Lowe	movq	%rdi, %rsi			/* rsi - lock ptr */
508*5d9d9091SRichard Lowe	movl	$LS_RW_EXIT_RELEASE, %edi
509*5d9d9091SRichard Lowe	movl	$RW_WRITER, %edx
510*5d9d9091SRichard Lowe	jmp	lockstat_wrapper_arg
511*5d9d9091SRichard Lowe	SET_SIZE(rw_exit)
512*5d9d9091SRichard Lowe
513*5d9d9091SRichard Lowe#if defined(OPTERON_ERRATUM_147)
514*5d9d9091SRichard Lowe
515*5d9d9091SRichard Lowe/*
516*5d9d9091SRichard Lowe * Track if erratum 147 workaround has been hotpatched into place.
517*5d9d9091SRichard Lowe */
518*5d9d9091SRichard Lowe	DGDEF3(erratum_147_patched, 4, 4)
519*5d9d9091SRichard Lowe	.long	0
520*5d9d9091SRichard Lowe
521*5d9d9091SRichard Lowe#define HOT_MUTEX_PATCH(iaddr, insn_reg)	\
522*5d9d9091SRichard Lowe	movq	$iaddr, %rdi;		\
523*5d9d9091SRichard Lowe	movl	%insn_reg, %esi;	\
524*5d9d9091SRichard Lowe	movl	$4, %edx;		\
525*5d9d9091SRichard Lowe	call	hot_patch_kernel_text;
526*5d9d9091SRichard Lowe
527*5d9d9091SRichard Lowe
528*5d9d9091SRichard Lowe/*
529*5d9d9091SRichard Lowe * void
530*5d9d9091SRichard Lowe * patch_erratum_147(void)
531*5d9d9091SRichard Lowe *
532*5d9d9091SRichard Lowe * Patch lock operations to work around erratum 147.
533*5d9d9091SRichard Lowe *
534*5d9d9091SRichard Lowe * The workaround is to place a fencing instruction (lfence) between the
535*5d9d9091SRichard Lowe * mutex operation and the subsequent read-modify-write instruction.
536*5d9d9091SRichard Lowe */
537*5d9d9091SRichard Lowe
538*5d9d9091SRichard Lowe	ENTRY_NP(patch_erratum_147)
539*5d9d9091SRichard Lowe	pushq	%rbp
540*5d9d9091SRichard Lowe	movq	%rsp, %rbp
541*5d9d9091SRichard Lowe	pushq	%r12
542*5d9d9091SRichard Lowe
543*5d9d9091SRichard Lowe	/*
544*5d9d9091SRichard Lowe	 * Patch `nop; nop; nop; nop` sequence to `lfence; nop`.  Since those
545*5d9d9091SRichard Lowe	 * patch points have been aligned to a 4-byte boundary, we can be
546*5d9d9091SRichard Lowe	 * confident that hot_patch_kernel_text() will be able to proceed
547*5d9d9091SRichard Lowe	 * safely and successfully.
548*5d9d9091SRichard Lowe	 */
549*5d9d9091SRichard Lowe	movl	$0x90e8ae0f, %r12d
550*5d9d9091SRichard Lowe	HOT_MUTEX_PATCH(.mutex_enter_147_patch_point, r12d)
551*5d9d9091SRichard Lowe	HOT_MUTEX_PATCH(.mutex_tryenter_147_patch_point, r12d)
552*5d9d9091SRichard Lowe	HOT_MUTEX_PATCH(.mutex_atryenter_147_patch_point, r12d)
553*5d9d9091SRichard Lowe	HOT_MUTEX_PATCH(.rw_write_enter_147_patch_point, r12d)
554*5d9d9091SRichard Lowe
555*5d9d9091SRichard Lowe	/* Record that erratum 147 points have been hotpatched */
556*5d9d9091SRichard Lowe	movl	$1, erratum_147_patched
557*5d9d9091SRichard Lowe
558*5d9d9091SRichard Lowe	popq	%r12
559*5d9d9091SRichard Lowe	movq	%rbp, %rsp
560*5d9d9091SRichard Lowe	popq	%rbp
561*5d9d9091SRichard Lowe	ret
562*5d9d9091SRichard Lowe	SET_SIZE(patch_erratum_147)
563*5d9d9091SRichard Lowe
564*5d9d9091SRichard Lowe#endif	/* OPTERON_ERRATUM_147 */
565*5d9d9091SRichard Lowe
566*5d9d9091SRichard Lowe	/*
567*5d9d9091SRichard Lowe	 * void
568*5d9d9091SRichard Lowe	 * lockstat_hotpatch_site(caddr_t instr_addr, int do_enable)
569*5d9d9091SRichard Lowe	 */
570*5d9d9091SRichard Lowe	ENTRY(lockstat_hotpatch_site)
571*5d9d9091SRichard Lowe	pushq	%rbp
572*5d9d9091SRichard Lowe	movq	%rsp, %rbp
573*5d9d9091SRichard Lowe	pushq	%rdi
574*5d9d9091SRichard Lowe	pushq	%rsi
575*5d9d9091SRichard Lowe
576*5d9d9091SRichard Lowe	testl	%esi, %esi
577*5d9d9091SRichard Lowe	jz	.do_disable
578*5d9d9091SRichard Lowe
579*5d9d9091SRichard Lowe	/* enable the probe (replace ret with nop) */
580*5d9d9091SRichard Lowe	movl	$NOP_INSTR, %esi
581*5d9d9091SRichard Lowe	movl	$1, %edx
582*5d9d9091SRichard Lowe	call	hot_patch_kernel_text
583*5d9d9091SRichard Lowe	leave
584*5d9d9091SRichard Lowe	ret
585*5d9d9091SRichard Lowe
586*5d9d9091SRichard Lowe.do_disable:
587*5d9d9091SRichard Lowe	/* disable the probe (replace nop with ret) */
588*5d9d9091SRichard Lowe	movl	$RET_INSTR, %esi
589*5d9d9091SRichard Lowe	movl	$1, %edx
590*5d9d9091SRichard Lowe	call	hot_patch_kernel_text
591*5d9d9091SRichard Lowe	leave
592*5d9d9091SRichard Lowe	ret
593*5d9d9091SRichard Lowe	SET_SIZE(lockstat_hotpatch_site)
594*5d9d9091SRichard Lowe
595*5d9d9091SRichard Lowe#define	HOT_PATCH_MATCH(name, probe, reg)			\
596*5d9d9091SRichard Lowe	cmpl	$probe, %reg;					\
597*5d9d9091SRichard Lowe	jne	1f;						\
598*5d9d9091SRichard Lowe	leaq	lockstat_probemap(%rip), %rax;			\
599*5d9d9091SRichard Lowe	movl	_MUL(probe, DTRACE_IDSIZE)(%rax), %esi;		\
600*5d9d9091SRichard Lowe	movq	$.##name##_lockstat_patch_point, %rdi;	\
601*5d9d9091SRichard Lowe	call	lockstat_hotpatch_site;				\
602*5d9d9091SRichard Lowe	1:
603*5d9d9091SRichard Lowe
604*5d9d9091SRichard Lowe/*
605*5d9d9091SRichard Lowe * void
606*5d9d9091SRichard Lowe * lockstat_hotpatch_probe(int ls_probe)
607*5d9d9091SRichard Lowe *
608*5d9d9091SRichard Lowe * Given a lockstat probe identifier, hotpatch any associated lockstat
609*5d9d9091SRichard Lowe * primitive routine(s) so they fall through into the lockstat_probe() call (if
610*5d9d9091SRichard Lowe * the probe is enabled) or return normally (when the probe is disabled).
611*5d9d9091SRichard Lowe */
612*5d9d9091SRichard Lowe
613*5d9d9091SRichard Lowe	ENTRY(lockstat_hotpatch_probe)
614*5d9d9091SRichard Lowe	pushq	%rbp
615*5d9d9091SRichard Lowe	movq	%rsp, %rbp
616*5d9d9091SRichard Lowe	pushq	%r12
617*5d9d9091SRichard Lowe	movl	%edi, %r12d
618*5d9d9091SRichard Lowe
619*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(mutex_enter, LS_MUTEX_ENTER_ACQUIRE, r12d)
620*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(mutex_tryenter, LS_MUTEX_TRYENTER_ACQUIRE, r12d)
621*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(mutex_exit, LS_MUTEX_EXIT_RELEASE, r12d)
622*5d9d9091SRichard Lowe
623*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(rw_write_enter, LS_RW_ENTER_ACQUIRE, r12d)
624*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(rw_read_enter, LS_RW_ENTER_ACQUIRE, r12d)
625*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(rw_write_exit, LS_RW_EXIT_RELEASE, r12d)
626*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(rw_read_exit, LS_RW_EXIT_RELEASE, r12d)
627*5d9d9091SRichard Lowe
628*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(lock_set, LS_LOCK_SET_ACQUIRE, r12d)
629*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(lock_try, LS_LOCK_TRY_ACQUIRE, r12d)
630*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(lock_clear, LS_LOCK_CLEAR_RELEASE, r12d)
631*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(lock_set_spl, LS_LOCK_SET_SPL_ACQUIRE, r12d)
632*5d9d9091SRichard Lowe	HOT_PATCH_MATCH(lock_clear_splx, LS_LOCK_CLEAR_SPLX_RELEASE, r12d)
633*5d9d9091SRichard Lowe
634*5d9d9091SRichard Lowe	popq	%r12
635*5d9d9091SRichard Lowe	leave
636*5d9d9091SRichard Lowe	ret
637*5d9d9091SRichard Lowe	SET_SIZE(lockstat_hotpatch_probe)
638*5d9d9091SRichard Lowe
639*5d9d9091SRichard Lowe	ENTRY(membar_enter)
640*5d9d9091SRichard Lowe	ALTENTRY(membar_exit)
641*5d9d9091SRichard Lowe	ALTENTRY(membar_sync)
642*5d9d9091SRichard Lowe	mfence			/* lighter weight than lock; xorq $0,(%rsp) */
643*5d9d9091SRichard Lowe	ret
644*5d9d9091SRichard Lowe	SET_SIZE(membar_sync)
645*5d9d9091SRichard Lowe	SET_SIZE(membar_exit)
646*5d9d9091SRichard Lowe	SET_SIZE(membar_enter)
647*5d9d9091SRichard Lowe
648*5d9d9091SRichard Lowe	ENTRY(membar_producer)
649*5d9d9091SRichard Lowe	sfence
650*5d9d9091SRichard Lowe	ret
651*5d9d9091SRichard Lowe	SET_SIZE(membar_producer)
652*5d9d9091SRichard Lowe
653*5d9d9091SRichard Lowe	ENTRY(membar_consumer)
654*5d9d9091SRichard Lowe	lfence
655*5d9d9091SRichard Lowe	ret
656*5d9d9091SRichard Lowe	SET_SIZE(membar_consumer)
657*5d9d9091SRichard Lowe
658*5d9d9091SRichard Lowe/*
659*5d9d9091SRichard Lowe * thread_onproc()
660*5d9d9091SRichard Lowe * Set thread in onproc state for the specified CPU.
661*5d9d9091SRichard Lowe * Also set the thread lock pointer to the CPU's onproc lock.
662*5d9d9091SRichard Lowe * Since the new lock isn't held, the store ordering is important.
663*5d9d9091SRichard Lowe * If not done in assembler, the compiler could reorder the stores.
664*5d9d9091SRichard Lowe */
665*5d9d9091SRichard Lowe
666*5d9d9091SRichard Lowe	ENTRY(thread_onproc)
667*5d9d9091SRichard Lowe	addq	$CPU_THREAD_LOCK, %rsi	/* pointer to disp_lock while running */
668*5d9d9091SRichard Lowe	movl	$ONPROC_THREAD, T_STATE(%rdi)	/* set state to TS_ONPROC */
669*5d9d9091SRichard Lowe	movq	%rsi, T_LOCKP(%rdi)	/* store new lock pointer */
670*5d9d9091SRichard Lowe	ret
671*5d9d9091SRichard Lowe	SET_SIZE(thread_onproc)
672*5d9d9091SRichard Lowe
673*5d9d9091SRichard Lowe/*
674*5d9d9091SRichard Lowe * mutex_delay_default(void)
675*5d9d9091SRichard Lowe * Spins for approx a few hundred processor cycles and returns to caller.
676*5d9d9091SRichard Lowe */
677*5d9d9091SRichard Lowe
678*5d9d9091SRichard Lowe	ENTRY(mutex_delay_default)
679*5d9d9091SRichard Lowe	movq	$92,%r11
680*5d9d9091SRichard Lowe0:	decq	%r11
681*5d9d9091SRichard Lowe	jg	0b
682*5d9d9091SRichard Lowe	ret
683*5d9d9091SRichard Lowe	SET_SIZE(mutex_delay_default)
684