xref: /illumos-gate/usr/src/uts/intel/sys/asm_linkage.h (revision f0089e39)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*f0089e39SRichard Lowe  * Common Development and Distribution License (the "License").
6*f0089e39SRichard Lowe  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*f0089e39SRichard Lowe 
227c478bd9Sstevel@tonic-gate /*
23*f0089e39SRichard Lowe  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*f0089e39SRichard Lowe /*
28*f0089e39SRichard Lowe  * Copyright 2019 Joyent, Inc.
29*f0089e39SRichard Lowe  */
30*f0089e39SRichard Lowe 
317c478bd9Sstevel@tonic-gate #ifndef _SYS_ASM_LINKAGE_H
327c478bd9Sstevel@tonic-gate #define	_SYS_ASM_LINKAGE_H
337c478bd9Sstevel@tonic-gate 
34*f0089e39SRichard Lowe #include <sys/stack.h>
35*f0089e39SRichard Lowe #include <sys/trap.h>
36*f0089e39SRichard Lowe 
37*f0089e39SRichard Lowe #ifdef	__cplusplus
38*f0089e39SRichard Lowe extern "C" {
39*f0089e39SRichard Lowe #endif
40*f0089e39SRichard Lowe 
41*f0089e39SRichard Lowe #ifdef _ASM	/* The remainder of this file is only for assembly files */
42*f0089e39SRichard Lowe 
43*f0089e39SRichard Lowe /*
44*f0089e39SRichard Lowe  * make annoying differences in assembler syntax go away
45*f0089e39SRichard Lowe  */
46*f0089e39SRichard Lowe 
47*f0089e39SRichard Lowe /*
48*f0089e39SRichard Lowe  * D16 and A16 are used to insert instructions prefixes; the
49*f0089e39SRichard Lowe  * macros help the assembler code be slightly more portable.
50*f0089e39SRichard Lowe  */
51*f0089e39SRichard Lowe #if !defined(__GNUC_AS__)
52*f0089e39SRichard Lowe /*
53*f0089e39SRichard Lowe  * /usr/ccs/bin/as prefixes are parsed as separate instructions
54*f0089e39SRichard Lowe  */
55*f0089e39SRichard Lowe #define	D16	data16;
56*f0089e39SRichard Lowe #define	A16	addr16;
57*f0089e39SRichard Lowe 
58*f0089e39SRichard Lowe /*
59*f0089e39SRichard Lowe  * (There are some weird constructs in constant expressions)
60*f0089e39SRichard Lowe  */
61*f0089e39SRichard Lowe #define	_CONST(const)		[const]
62*f0089e39SRichard Lowe #define	_BITNOT(const)		-1!_CONST(const)
63*f0089e39SRichard Lowe #define	_MUL(a, b)		_CONST(a \* b)
64*f0089e39SRichard Lowe 
65*f0089e39SRichard Lowe #else
66*f0089e39SRichard Lowe /*
67*f0089e39SRichard Lowe  * Why not use the 'data16' and 'addr16' prefixes .. well, the
68*f0089e39SRichard Lowe  * assembler doesn't quite believe in real mode, and thus argues with
69*f0089e39SRichard Lowe  * us about what we're trying to do.
70*f0089e39SRichard Lowe  */
71*f0089e39SRichard Lowe #define	D16	.byte	0x66;
72*f0089e39SRichard Lowe #define	A16	.byte	0x67;
73*f0089e39SRichard Lowe 
74*f0089e39SRichard Lowe #define	_CONST(const)		(const)
75*f0089e39SRichard Lowe #define	_BITNOT(const)		~_CONST(const)
76*f0089e39SRichard Lowe #define	_MUL(a, b)		_CONST(a * b)
77*f0089e39SRichard Lowe 
78*f0089e39SRichard Lowe #endif
79*f0089e39SRichard Lowe 
80*f0089e39SRichard Lowe /*
81*f0089e39SRichard Lowe  * C pointers are different sizes between i386 and amd64.
82*f0089e39SRichard Lowe  * These constants can be used to compute offsets into pointer arrays.
83*f0089e39SRichard Lowe  */
84*f0089e39SRichard Lowe #if defined(__amd64)
85*f0089e39SRichard Lowe #define	CLONGSHIFT	3
86*f0089e39SRichard Lowe #define	CLONGSIZE	8
87*f0089e39SRichard Lowe #define	CLONGMASK	7
88*f0089e39SRichard Lowe #elif defined(__i386)
89*f0089e39SRichard Lowe #define	CLONGSHIFT	2
90*f0089e39SRichard Lowe #define	CLONGSIZE	4
91*f0089e39SRichard Lowe #define	CLONGMASK	3
92*f0089e39SRichard Lowe #endif
93*f0089e39SRichard Lowe 
94*f0089e39SRichard Lowe /*
95*f0089e39SRichard Lowe  * Since we know we're either ILP32 or LP64 ..
96*f0089e39SRichard Lowe  */
97*f0089e39SRichard Lowe #define	CPTRSHIFT	CLONGSHIFT
98*f0089e39SRichard Lowe #define	CPTRSIZE	CLONGSIZE
99*f0089e39SRichard Lowe #define	CPTRMASK	CLONGMASK
100*f0089e39SRichard Lowe 
101*f0089e39SRichard Lowe #if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT)
102*f0089e39SRichard Lowe #error	"inconsistent shift constants"
103*f0089e39SRichard Lowe #endif
104*f0089e39SRichard Lowe 
105*f0089e39SRichard Lowe #if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1)
106*f0089e39SRichard Lowe #error	"inconsistent mask constants"
107*f0089e39SRichard Lowe #endif
108*f0089e39SRichard Lowe 
109*f0089e39SRichard Lowe #define	ASM_ENTRY_ALIGN	16
110*f0089e39SRichard Lowe 
111*f0089e39SRichard Lowe /*
112*f0089e39SRichard Lowe  * SSE register alignment and save areas
113*f0089e39SRichard Lowe  */
114*f0089e39SRichard Lowe 
115*f0089e39SRichard Lowe #define	XMM_SIZE	16
116*f0089e39SRichard Lowe #define	XMM_ALIGN	16
117*f0089e39SRichard Lowe 
118*f0089e39SRichard Lowe #if defined(__amd64)
119*f0089e39SRichard Lowe 
120*f0089e39SRichard Lowe #define	SAVE_XMM_PROLOG(sreg, nreg)				\
121*f0089e39SRichard Lowe 	subq	$_CONST(_MUL(XMM_SIZE, nreg)), %rsp;		\
122*f0089e39SRichard Lowe 	movq	%rsp, sreg
123*f0089e39SRichard Lowe 
124*f0089e39SRichard Lowe #define	RSTOR_XMM_EPILOG(sreg, nreg)				\
125*f0089e39SRichard Lowe 	addq	$_CONST(_MUL(XMM_SIZE, nreg)), %rsp
126*f0089e39SRichard Lowe 
127*f0089e39SRichard Lowe #elif defined(__i386)
128*f0089e39SRichard Lowe 
129*f0089e39SRichard Lowe #define	SAVE_XMM_PROLOG(sreg, nreg)				\
130*f0089e39SRichard Lowe 	subl	$_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; \
131*f0089e39SRichard Lowe 	movl	%esp, sreg;					\
132*f0089e39SRichard Lowe 	addl	$XMM_ALIGN, sreg;				\
133*f0089e39SRichard Lowe 	andl	$_BITNOT(XMM_ALIGN-1), sreg
134*f0089e39SRichard Lowe 
135*f0089e39SRichard Lowe #define	RSTOR_XMM_EPILOG(sreg, nreg)				\
136*f0089e39SRichard Lowe 	addl	$_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp;
137*f0089e39SRichard Lowe 
138*f0089e39SRichard Lowe #endif	/* __i386 */
139*f0089e39SRichard Lowe 
140*f0089e39SRichard Lowe /*
141*f0089e39SRichard Lowe  * profiling causes definitions of the MCOUNT and RTMCOUNT
142*f0089e39SRichard Lowe  * particular to the type
143*f0089e39SRichard Lowe  */
144*f0089e39SRichard Lowe #ifdef GPROF
145*f0089e39SRichard Lowe 
146*f0089e39SRichard Lowe #define	MCOUNT(x) \
147*f0089e39SRichard Lowe 	pushl	%ebp; \
148*f0089e39SRichard Lowe 	movl	%esp, %ebp; \
149*f0089e39SRichard Lowe 	call	_mcount; \
150*f0089e39SRichard Lowe 	popl	%ebp
151*f0089e39SRichard Lowe 
152*f0089e39SRichard Lowe #endif /* GPROF */
153*f0089e39SRichard Lowe 
154*f0089e39SRichard Lowe #ifdef PROF
155*f0089e39SRichard Lowe 
156*f0089e39SRichard Lowe #define	MCOUNT(x) \
157*f0089e39SRichard Lowe /* CSTYLED */ \
158*f0089e39SRichard Lowe 	.lcomm .L_/**/x/**/1, 4, 4; \
159*f0089e39SRichard Lowe 	pushl	%ebp; \
160*f0089e39SRichard Lowe 	movl	%esp, %ebp; \
161*f0089e39SRichard Lowe /* CSTYLED */ \
162*f0089e39SRichard Lowe 	movl	$.L_/**/x/**/1, %edx; \
163*f0089e39SRichard Lowe 	call	_mcount; \
164*f0089e39SRichard Lowe 	popl	%ebp
165*f0089e39SRichard Lowe 
166*f0089e39SRichard Lowe #endif /* PROF */
167*f0089e39SRichard Lowe 
168*f0089e39SRichard Lowe /*
169*f0089e39SRichard Lowe  * if we are not profiling, MCOUNT should be defined to nothing
170*f0089e39SRichard Lowe  */
171*f0089e39SRichard Lowe #if !defined(PROF) && !defined(GPROF)
172*f0089e39SRichard Lowe #define	MCOUNT(x)
173*f0089e39SRichard Lowe #endif /* !defined(PROF) && !defined(GPROF) */
174*f0089e39SRichard Lowe 
175*f0089e39SRichard Lowe #define	RTMCOUNT(x)	MCOUNT(x)
176*f0089e39SRichard Lowe 
177*f0089e39SRichard Lowe /*
178*f0089e39SRichard Lowe  * Macro to define weak symbol aliases. These are similar to the ANSI-C
179*f0089e39SRichard Lowe  *	#pragma weak _name = name
180*f0089e39SRichard Lowe  * except a compiler can determine type. The assembler must be told. Hence,
181*f0089e39SRichard Lowe  * the second parameter must be the type of the symbol (i.e.: function,...)
182*f0089e39SRichard Lowe  */
183*f0089e39SRichard Lowe #define	ANSI_PRAGMA_WEAK(sym, stype)	\
184*f0089e39SRichard Lowe /* CSTYLED */ \
185*f0089e39SRichard Lowe 	.weak	_/**/sym; \
186*f0089e39SRichard Lowe /* CSTYLED */ \
187*f0089e39SRichard Lowe 	.type	_/**/sym, @stype; \
188*f0089e39SRichard Lowe /* CSTYLED */ \
189*f0089e39SRichard Lowe _/**/sym = sym
190*f0089e39SRichard Lowe 
191*f0089e39SRichard Lowe /*
192*f0089e39SRichard Lowe  * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in:
193*f0089e39SRichard Lowe  *	#pragma weak sym1 = sym2
194*f0089e39SRichard Lowe  */
195*f0089e39SRichard Lowe #define	ANSI_PRAGMA_WEAK2(sym1, sym2, stype)	\
196*f0089e39SRichard Lowe 	.weak	sym1; \
197*f0089e39SRichard Lowe 	.type sym1, @stype; \
198*f0089e39SRichard Lowe sym1	= sym2
199*f0089e39SRichard Lowe 
200*f0089e39SRichard Lowe /*
201*f0089e39SRichard Lowe  * ENTRY provides the standard procedure entry code and an easy way to
202*f0089e39SRichard Lowe  * insert the calls to mcount for profiling. ENTRY_NP is identical, but
203*f0089e39SRichard Lowe  * never calls mcount.
204*f0089e39SRichard Lowe  */
205*f0089e39SRichard Lowe #define	ENTRY(x) \
206*f0089e39SRichard Lowe 	.text; \
207*f0089e39SRichard Lowe 	.align	ASM_ENTRY_ALIGN; \
208*f0089e39SRichard Lowe 	.globl	x; \
209*f0089e39SRichard Lowe 	.type	x, @function; \
210*f0089e39SRichard Lowe x:	MCOUNT(x)
211*f0089e39SRichard Lowe 
212*f0089e39SRichard Lowe #define	ENTRY_NP(x) \
213*f0089e39SRichard Lowe 	.text; \
214*f0089e39SRichard Lowe 	.align	ASM_ENTRY_ALIGN; \
215*f0089e39SRichard Lowe 	.globl	x; \
216*f0089e39SRichard Lowe 	.type	x, @function; \
217*f0089e39SRichard Lowe x:
218*f0089e39SRichard Lowe 
219*f0089e39SRichard Lowe #define	RTENTRY(x) \
220*f0089e39SRichard Lowe 	.text; \
221*f0089e39SRichard Lowe 	.align	ASM_ENTRY_ALIGN; \
222*f0089e39SRichard Lowe 	.globl	x; \
223*f0089e39SRichard Lowe 	.type	x, @function; \
224*f0089e39SRichard Lowe x:	RTMCOUNT(x)
225*f0089e39SRichard Lowe 
226*f0089e39SRichard Lowe /*
227*f0089e39SRichard Lowe  * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
228*f0089e39SRichard Lowe  */
229*f0089e39SRichard Lowe #define	ENTRY2(x, y) \
230*f0089e39SRichard Lowe 	.text; \
231*f0089e39SRichard Lowe 	.align	ASM_ENTRY_ALIGN; \
232*f0089e39SRichard Lowe 	.globl	x, y; \
233*f0089e39SRichard Lowe 	.type	x, @function; \
234*f0089e39SRichard Lowe 	.type	y, @function; \
235*f0089e39SRichard Lowe /* CSTYLED */ \
236*f0089e39SRichard Lowe x:	; \
237*f0089e39SRichard Lowe y:	MCOUNT(x)
238*f0089e39SRichard Lowe 
239*f0089e39SRichard Lowe #define	ENTRY_NP2(x, y) \
240*f0089e39SRichard Lowe 	.text; \
241*f0089e39SRichard Lowe 	.align	ASM_ENTRY_ALIGN; \
242*f0089e39SRichard Lowe 	.globl	x, y; \
243*f0089e39SRichard Lowe 	.type	x, @function; \
244*f0089e39SRichard Lowe 	.type	y, @function; \
245*f0089e39SRichard Lowe /* CSTYLED */ \
246*f0089e39SRichard Lowe x:	; \
247*f0089e39SRichard Lowe y:
248*f0089e39SRichard Lowe 
249*f0089e39SRichard Lowe 
250*f0089e39SRichard Lowe /*
251*f0089e39SRichard Lowe  * ALTENTRY provides for additional entry points.
252*f0089e39SRichard Lowe  */
253*f0089e39SRichard Lowe #define	ALTENTRY(x) \
254*f0089e39SRichard Lowe 	.globl x; \
255*f0089e39SRichard Lowe 	.type	x, @function; \
256*f0089e39SRichard Lowe x:
257*f0089e39SRichard Lowe 
258*f0089e39SRichard Lowe /*
259*f0089e39SRichard Lowe  * DGDEF and DGDEF2 provide global data declarations.
260*f0089e39SRichard Lowe  *
261*f0089e39SRichard Lowe  * DGDEF provides a word aligned word of storage.
262*f0089e39SRichard Lowe  *
263*f0089e39SRichard Lowe  * DGDEF2 allocates "sz" bytes of storage with **NO** alignment.  This
264*f0089e39SRichard Lowe  * implies this macro is best used for byte arrays.
265*f0089e39SRichard Lowe  *
266*f0089e39SRichard Lowe  * DGDEF3 allocates "sz" bytes of storage with "algn" alignment.
267*f0089e39SRichard Lowe  */
268*f0089e39SRichard Lowe #define	DGDEF2(name, sz) \
269*f0089e39SRichard Lowe 	.data; \
270*f0089e39SRichard Lowe 	.globl	name; \
271*f0089e39SRichard Lowe 	.type	name, @object; \
272*f0089e39SRichard Lowe 	.size	name, sz; \
273*f0089e39SRichard Lowe name:
274*f0089e39SRichard Lowe 
275*f0089e39SRichard Lowe #define	DGDEF3(name, sz, algn) \
276*f0089e39SRichard Lowe 	.data; \
277*f0089e39SRichard Lowe 	.align	algn; \
278*f0089e39SRichard Lowe 	.globl	name; \
279*f0089e39SRichard Lowe 	.type	name, @object; \
280*f0089e39SRichard Lowe 	.size	name, sz; \
281*f0089e39SRichard Lowe name:
282*f0089e39SRichard Lowe 
283*f0089e39SRichard Lowe #define	DGDEF(name)	DGDEF3(name, 4, 4)
284*f0089e39SRichard Lowe 
285*f0089e39SRichard Lowe /*
286*f0089e39SRichard Lowe  * SET_SIZE trails a function and set the size for the ELF symbol table.
287*f0089e39SRichard Lowe  */
288*f0089e39SRichard Lowe #define	SET_SIZE(x) \
289*f0089e39SRichard Lowe 	.size	x, [.-x]
290*f0089e39SRichard Lowe 
291*f0089e39SRichard Lowe /*
292*f0089e39SRichard Lowe  * NWORD provides native word value.
293*f0089e39SRichard Lowe  */
294*f0089e39SRichard Lowe #if defined(__amd64)
295*f0089e39SRichard Lowe 
296*f0089e39SRichard Lowe /*CSTYLED*/
297*f0089e39SRichard Lowe #define	NWORD	quad
298*f0089e39SRichard Lowe 
299*f0089e39SRichard Lowe #elif defined(__i386)
300*f0089e39SRichard Lowe 
301*f0089e39SRichard Lowe #define	NWORD	long
302*f0089e39SRichard Lowe 
303*f0089e39SRichard Lowe #endif  /* __i386 */
304*f0089e39SRichard Lowe 
305*f0089e39SRichard Lowe /*
306*f0089e39SRichard Lowe  * These macros should be used when making indirect calls in the kernel. They
307*f0089e39SRichard Lowe  * will perform a jump or call to the corresponding register in a way that knows
308*f0089e39SRichard Lowe  * about retpolines and handles whether such mitigations are enabled or not.
309*f0089e39SRichard Lowe  *
310*f0089e39SRichard Lowe  * INDIRECT_JMP_REG will jump to named register. INDIRECT_CALL_REG will instead
311*f0089e39SRichard Lowe  * do a call. These macros cannot be used to dereference a register. For
312*f0089e39SRichard Lowe  * example, if you need to do something that looks like the following:
313*f0089e39SRichard Lowe  *
314*f0089e39SRichard Lowe  *	call	*24(%rdi)
315*f0089e39SRichard Lowe  *	jmp	*(%r15)
316*f0089e39SRichard Lowe  *
317*f0089e39SRichard Lowe  * You must instead first do a movq into the corresponding location. You need to
318*f0089e39SRichard Lowe  * be careful to make sure that the register that its loaded into is safe to
319*f0089e39SRichard Lowe  * use. Often that register may be saved or used elsewhere so it may not be safe
320*f0089e39SRichard Lowe  * to clobber the value. Usually, loading into %rax would be safe. These would
321*f0089e39SRichard Lowe  * turn into something like:
322*f0089e39SRichard Lowe  *
323*f0089e39SRichard Lowe  *	movq 24(%rdi), %rdi; INDIRECT_CALL_REG(rdi)
324*f0089e39SRichard Lowe  *	movq (%r15), %r15; INDIRECT_JMP_REG(r15)
325*f0089e39SRichard Lowe  *
326*f0089e39SRichard Lowe  * If you are trying to call a global function, then use the following pattern
327*f0089e39SRichard Lowe  * (substituting the register in question):
328*f0089e39SRichard Lowe  *
329*f0089e39SRichard Lowe  *	leaq	my_favorite_function(%rip), %rax
330*f0089e39SRichard Lowe  *	INDIRECT_CALL_REG(rax)
331*f0089e39SRichard Lowe  *
332*f0089e39SRichard Lowe  * If you instead have a function pointer (say gethrtimef for example), then you
333*f0089e39SRichard Lowe  * need to do:
334*f0089e39SRichard Lowe  *
335*f0089e39SRichard Lowe  *	movq	my_favorite_function_pointer(%rip), %rax
336*f0089e39SRichard Lowe  *	INDIRECT_CALL_REG(rax)
337*f0089e39SRichard Lowe  */
338*f0089e39SRichard Lowe 
339*f0089e39SRichard Lowe /* CSTYLED */
340*f0089e39SRichard Lowe #define	INDIRECT_JMP_REG(reg)	jmp	__x86_indirect_thunk_/**/reg;
3417c478bd9Sstevel@tonic-gate 
342*f0089e39SRichard Lowe /* CSTYLED */
343*f0089e39SRichard Lowe #define	INDIRECT_CALL_REG(reg)	call	__x86_indirect_thunk_/**/reg;
3447c478bd9Sstevel@tonic-gate 
345*f0089e39SRichard Lowe #endif /* _ASM */
3467c478bd9Sstevel@tonic-gate 
347*f0089e39SRichard Lowe #ifdef	__cplusplus
348*f0089e39SRichard Lowe }
3497c478bd9Sstevel@tonic-gate #endif
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate #endif	/* _SYS_ASM_LINKAGE_H */
352