1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _S10_MISC_H
27 #define	_S10_MISC_H
28 
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 /*
34  * This header file must uses _ASM defines to allow it to be included
35  * in assmebly source files
36  */
37 #include <sys/asm_linkage.h>
38 #include <sys/regset.h>
39 #include <sys/syscall.h>
40 #include "assym.h"
41 
42 /*
43  * Our syscall emulation callback handler adds one argument to each
44  * system call, so we'll need to allocate space for one more argument
45  * above the maximum number of arguments that a system call can normally
46  * take.  Also, we assume that each syscall argument is a long, ie, we
47  * don't support long long syscall parameters.
48  */
49 #if defined(__sparc)
50 /*
51  * 32-bit and 64-bit sparc syscalls can take up to 8 arguments.
52  * 32-bit sparc indirect syscalls can take up to 9 arguments.
53  * Arguments 1 - 6 are passed via %o0 - %o5.
54  * Additional arguments are passed on the stack.
55  * So make space for 4 arguments on the stack.
56  */
57 #define	EH_ARGS_COUNT		4
58 #elif defined(__amd64)
59 /*
60  * amd64 syscalls can take up to 8 arguments.
61  * Arguments 1 - 6 are passed via: %rdi, %rsi, %rdx, %r10, %r8, %r9
62  * Additional arguments are passed on the stack.
63  * So make space for 3 arguments on the stack.
64  */
65 #define	EH_ARGS_COUNT		3
66 #else /* !__sparc && !__amd64 */
67 /*
68  * ia32 syscalls can take up to 8 arguments.
69  * All arguments are passed on the stack.
70  * So make space for 9 arguments on the stack.
71  */
72 #define	EH_ARGS_COUNT		9
73 #endif /* !__sparc && !__amd64 */
74 
75 
76 #define	EH_ARGS_SIZE		(CPTRSIZE * EH_ARGS_COUNT)
77 #define	EH_ARGS_OFFSET(x)	(STACK_BIAS + MINFRAME + (CPTRSIZE * (x)))
78 #define	EH_LOCALS_SIZE		(EH_ARGS_SIZE + SIZEOF_GREGSET_T + \
79 				    SIZEOF_SYSRET_T + CPTRSIZE)
80 
81 #if defined(__sparc)
82 /*
83  * On sparc, all emulation callback handler variable access is done
84  * relative to %sp, so access offsets are positive.
85  */
86 #define	EH_LOCALS_START		(STACK_BIAS + MINFRAME + EH_ARGS_SIZE)
87 #define	EH_LOCALS_END_TGT	(STACK_BIAS + MINFRAME + EH_LOCALS_SIZE)
88 #else /* !__sparc */
89 /*
90  * On x86, all emulation callback handler variable access is done
91  * relative to %ebp/%rbp, so access offsets are negative.
92  */
93 #define	EH_LOCALS_START		(-(EH_LOCALS_SIZE - \
94 				    (STACK_BIAS + MINFRAME + EH_ARGS_SIZE)))
95 #define	EH_LOCALS_END_TGT	0
96 #endif /* !__sparc */
97 
98 /*
99  * In our emulation callback handler, our stack will look like:
100  *		-------------------------------------------------
101  *	  %bp   | long		rvflag				|
102  *	   |    | sysret_t	sysret				|
103  *	   v    | gregset_t	gregs				|
104  *	  %sp   | long		callback args[EH_ARGS_COUNT]	|
105  *		-------------------------------------------------
106  * For ia32, use %ebp and %esp instead of %bp and %sp.
107  * For amd64, use %rbp and %rsp instead of %bp and %sp.
108  *
109  * Our emulation callback handler always saves enough space to hold the
110  * maximum number of stack arguments to a system call.  This is architecture
111  * specific and is defined via EH_ARGS_COUNT.
112  */
113 #define	EH_LOCALS_GREGS		(EH_LOCALS_START)
114 #define	EH_LOCALS_GREG(x)	(EH_LOCALS_GREGS + (SIZEOF_GREG_T * (x)))
115 #define	EH_LOCALS_SYSRET	(EH_LOCALS_GREGS + SIZEOF_GREGSET_T)
116 #define	EH_LOCALS_SYSRET1	(EH_LOCALS_SYSRET)
117 #define	EH_LOCALS_SYSRET2	(EH_LOCALS_SYSRET + CPTRSIZE)
118 #define	EH_LOCALS_RVFLAG	(EH_LOCALS_SYSRET + SIZEOF_SYSRET_T)
119 #define	EH_LOCALS_END		(EH_LOCALS_RVFLAG + CPTRSIZE)
120 
121 #if (EH_LOCALS_END != EH_LOCALS_END_TGT)
122 #error "s10_misc.h EH_LOCALS_* macros don't add up"
123 #endif /* (EH_LOCALS_END != EH_LOCALS_END_TGT) */
124 
125 /*
126  * The second parameter of each entry in the s10_sysent_table
127  * contains the number of parameters and flags that describe the
128  * syscall return value encoding.  See the block comments at the
129  * top of ../common/s10_brand.c for more information about the
130  * syscall return value flags and when they should be used.
131  */
132 #define	NARGS_MASK	0x000000FF	/* Mask for syscalls argument count */
133 #define	RV_MASK		0x0000FF00	/* Mask for return value flags */
134 #define	RV_DEFAULT	0x00000100	/* syscall returns "default" values */
135 #define	RV_32RVAL2	0x00000200	/* syscall returns two 32-bit values */
136 #define	RV_64RVAL	0x00000400	/* syscall returns a 64-bit value */
137 
138 #if !defined(_ASM)
139 
140 /*
141  * We define our own version of assert because the default one will
142  * try to emit a localized message.  That is bad because first, we can't
143  * emit messages to random file descriptors, and second localizing a message
144  * requires allocating memory and we can't do that either.
145  */
146 #define	s10_assert(ex)	(void)((ex) || \
147 				(_s10_abort(0, #ex, __FILE__, __LINE__), 0))
148 #define	s10_abort(err, msg)	_s10_abort((err), (msg), __FILE__, __LINE__)
149 
150 /*
151  * These macros invoke a brandsys subcommand, B_S10_TRUSS_POINT, used to expose
152  * a call to an interpositioned syscall that would have otherwise gone
153  * unnoticed by truss(1) because the interpositioned system call did not call
154  * any system calls before returning.
155  */
156 #define	S10_TRUSS_POINT_5(rval, syscall_num, err, a0, a1, a2, a3, a4) \
157 	__systemcall(rval, SYS_brand + 1024, \
158 	    B_S10_TRUSS_POINT, (syscall_num), (err), (a0), (a1), (a2), (a3), \
159 	    (a4))
160 
161 #define	S10_TRUSS_POINT_4(rval, syscall_num, err, a0, a1, a2, a3) \
162 	S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), (a3), 0)
163 
164 #define	S10_TRUSS_POINT_3(rval, syscall_num, err, a0, a1, a2) \
165 	S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), 0, 0)
166 
167 #define	S10_TRUSS_POINT_2(rval, syscall_num, err, a0, a1) \
168 	S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), 0, 0, 0)
169 
170 #define	S10_TRUSS_POINT_1(rval, syscall_num, err, a0) \
171 	S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), 0, 0, 0, 0)
172 
173 #define	S10_TRUSS_POINT_0(rval, syscall_num, err) \
174 	S10_TRUSS_POINT_5(rval, (syscall_num), (err), 0, 0, 0, 0, 0)
175 
176 /*
177  * From s10_runexe.s
178  */
179 extern void s10_runexe(void *, ulong_t);
180 
181 /*
182  * From s10_handler.s
183  */
184 extern void s10_handler(void);
185 extern void s10_error(void);
186 extern void s10_success(void);
187 
188 /*
189  * From s10_brand.c
190  */
191 extern void _s10_abort(int, const char *, const char *, int);
192 
193 #endif	/* !_ASM */
194 
195 #ifdef	__cplusplus
196 }
197 #endif
198 
199 #endif	/* _S10_MISC_H */
200