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