1628e3cbeSEdward Pilatowicz /*
2628e3cbeSEdward Pilatowicz  * CDDL HEADER START
3628e3cbeSEdward Pilatowicz  *
4628e3cbeSEdward Pilatowicz  * The contents of this file are subject to the terms of the
5628e3cbeSEdward Pilatowicz  * Common Development and Distribution License (the "License").
6628e3cbeSEdward Pilatowicz  * You may not use this file except in compliance with the License.
7628e3cbeSEdward Pilatowicz  *
8628e3cbeSEdward Pilatowicz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9628e3cbeSEdward Pilatowicz  * or http://www.opensolaris.org/os/licensing.
10628e3cbeSEdward Pilatowicz  * See the License for the specific language governing permissions
11628e3cbeSEdward Pilatowicz  * and limitations under the License.
12628e3cbeSEdward Pilatowicz  *
13628e3cbeSEdward Pilatowicz  * When distributing Covered Code, include this CDDL HEADER in each
14628e3cbeSEdward Pilatowicz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15628e3cbeSEdward Pilatowicz  * If applicable, add the following below this CDDL HEADER, with the
16628e3cbeSEdward Pilatowicz  * fields enclosed by brackets "[]" replaced with your own identifying
17628e3cbeSEdward Pilatowicz  * information: Portions Copyright [yyyy] [name of copyright owner]
18628e3cbeSEdward Pilatowicz  *
19628e3cbeSEdward Pilatowicz  * CDDL HEADER END
20628e3cbeSEdward Pilatowicz  */
21628e3cbeSEdward Pilatowicz /*
2280e2ca85S  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23628e3cbeSEdward Pilatowicz  */
24628e3cbeSEdward Pilatowicz 
2580e2ca85S #ifndef _BRAND_MISC_H
2680e2ca85S #define	_BRAND_MISC_H
27628e3cbeSEdward Pilatowicz 
28628e3cbeSEdward Pilatowicz #ifdef	__cplusplus
29628e3cbeSEdward Pilatowicz extern "C" {
30628e3cbeSEdward Pilatowicz #endif
31628e3cbeSEdward Pilatowicz 
32628e3cbeSEdward Pilatowicz /*
33628e3cbeSEdward Pilatowicz  * This header file must uses _ASM defines to allow it to be included
34628e3cbeSEdward Pilatowicz  * in assmebly source files
35628e3cbeSEdward Pilatowicz  */
36628e3cbeSEdward Pilatowicz #include <sys/asm_linkage.h>
37628e3cbeSEdward Pilatowicz #include <sys/regset.h>
38628e3cbeSEdward Pilatowicz #include <sys/syscall.h>
3980e2ca85S #if !defined(_ASM)
4080e2ca85S #include <sys/brand.h>
4180e2ca85S #endif
42628e3cbeSEdward Pilatowicz #include "assym.h"
43628e3cbeSEdward Pilatowicz 
44628e3cbeSEdward Pilatowicz /*
45628e3cbeSEdward Pilatowicz  * Our syscall emulation callback handler adds one argument to each
46628e3cbeSEdward Pilatowicz  * system call, so we'll need to allocate space for one more argument
47628e3cbeSEdward Pilatowicz  * above the maximum number of arguments that a system call can normally
48628e3cbeSEdward Pilatowicz  * take.  Also, we assume that each syscall argument is a long, ie, we
49628e3cbeSEdward Pilatowicz  * don't support long long syscall parameters.
50628e3cbeSEdward Pilatowicz  */
51628e3cbeSEdward Pilatowicz #if defined(__sparc)
52628e3cbeSEdward Pilatowicz /*
53628e3cbeSEdward Pilatowicz  * 32-bit and 64-bit sparc syscalls can take up to 8 arguments.
54628e3cbeSEdward Pilatowicz  * 32-bit sparc indirect syscalls can take up to 9 arguments.
55628e3cbeSEdward Pilatowicz  * Arguments 1 - 6 are passed via %o0 - %o5.
56628e3cbeSEdward Pilatowicz  * Additional arguments are passed on the stack.
57628e3cbeSEdward Pilatowicz  * So make space for 4 arguments on the stack.
58628e3cbeSEdward Pilatowicz  */
59628e3cbeSEdward Pilatowicz #define	EH_ARGS_COUNT		4
60628e3cbeSEdward Pilatowicz #elif defined(__amd64)
61628e3cbeSEdward Pilatowicz /*
62628e3cbeSEdward Pilatowicz  * amd64 syscalls can take up to 8 arguments.
63628e3cbeSEdward Pilatowicz  * Arguments 1 - 6 are passed via: %rdi, %rsi, %rdx, %r10, %r8, %r9
64628e3cbeSEdward Pilatowicz  * Additional arguments are passed on the stack.
65628e3cbeSEdward Pilatowicz  * So make space for 3 arguments on the stack.
66628e3cbeSEdward Pilatowicz  */
67628e3cbeSEdward Pilatowicz #define	EH_ARGS_COUNT		3
68628e3cbeSEdward Pilatowicz #else /* !__sparc && !__amd64 */
69628e3cbeSEdward Pilatowicz /*
70628e3cbeSEdward Pilatowicz  * ia32 syscalls can take up to 8 arguments.
71628e3cbeSEdward Pilatowicz  * All arguments are passed on the stack.
72628e3cbeSEdward Pilatowicz  * So make space for 9 arguments on the stack.
73628e3cbeSEdward Pilatowicz  */
74628e3cbeSEdward Pilatowicz #define	EH_ARGS_COUNT		9
75628e3cbeSEdward Pilatowicz #endif /* !__sparc && !__amd64 */
76628e3cbeSEdward Pilatowicz 
77628e3cbeSEdward Pilatowicz 
78628e3cbeSEdward Pilatowicz #define	EH_ARGS_SIZE		(CPTRSIZE * EH_ARGS_COUNT)
79628e3cbeSEdward Pilatowicz #define	EH_ARGS_OFFSET(x)	(STACK_BIAS + MINFRAME + (CPTRSIZE * (x)))
80628e3cbeSEdward Pilatowicz #define	EH_LOCALS_SIZE		(EH_ARGS_SIZE + SIZEOF_GREGSET_T + \
81628e3cbeSEdward Pilatowicz 				    SIZEOF_SYSRET_T + CPTRSIZE)
82628e3cbeSEdward Pilatowicz 
83628e3cbeSEdward Pilatowicz #if defined(__sparc)
84628e3cbeSEdward Pilatowicz /*
85628e3cbeSEdward Pilatowicz  * On sparc, all emulation callback handler variable access is done
86628e3cbeSEdward Pilatowicz  * relative to %sp, so access offsets are positive.
87628e3cbeSEdward Pilatowicz  */
88628e3cbeSEdward Pilatowicz #define	EH_LOCALS_START		(STACK_BIAS + MINFRAME + EH_ARGS_SIZE)
89628e3cbeSEdward Pilatowicz #define	EH_LOCALS_END_TGT	(STACK_BIAS + MINFRAME + EH_LOCALS_SIZE)
90628e3cbeSEdward Pilatowicz #else /* !__sparc */
91628e3cbeSEdward Pilatowicz /*
92628e3cbeSEdward Pilatowicz  * On x86, all emulation callback handler variable access is done
93628e3cbeSEdward Pilatowicz  * relative to %ebp/%rbp, so access offsets are negative.
94628e3cbeSEdward Pilatowicz  */
95628e3cbeSEdward Pilatowicz #define	EH_LOCALS_START		(-(EH_LOCALS_SIZE - \
96628e3cbeSEdward Pilatowicz 				    (STACK_BIAS + MINFRAME + EH_ARGS_SIZE)))
97628e3cbeSEdward Pilatowicz #define	EH_LOCALS_END_TGT	0
98628e3cbeSEdward Pilatowicz #endif /* !__sparc */
99628e3cbeSEdward Pilatowicz 
100628e3cbeSEdward Pilatowicz /*
101628e3cbeSEdward Pilatowicz  * In our emulation callback handler, our stack will look like:
102628e3cbeSEdward Pilatowicz  *		-------------------------------------------------
103628e3cbeSEdward Pilatowicz  *	  %bp   | long		rvflag				|
104628e3cbeSEdward Pilatowicz  *	   |    | sysret_t	sysret				|
105628e3cbeSEdward Pilatowicz  *	   v    | gregset_t	gregs				|
106628e3cbeSEdward Pilatowicz  *	  %sp   | long		callback args[EH_ARGS_COUNT]	|
107628e3cbeSEdward Pilatowicz  *		-------------------------------------------------
108628e3cbeSEdward Pilatowicz  * For ia32, use %ebp and %esp instead of %bp and %sp.
109628e3cbeSEdward Pilatowicz  * For amd64, use %rbp and %rsp instead of %bp and %sp.
110628e3cbeSEdward Pilatowicz  *
111628e3cbeSEdward Pilatowicz  * Our emulation callback handler always saves enough space to hold the
112628e3cbeSEdward Pilatowicz  * maximum number of stack arguments to a system call.  This is architecture
113628e3cbeSEdward Pilatowicz  * specific and is defined via EH_ARGS_COUNT.
114628e3cbeSEdward Pilatowicz  */
115628e3cbeSEdward Pilatowicz #define	EH_LOCALS_GREGS		(EH_LOCALS_START)
116628e3cbeSEdward Pilatowicz #define	EH_LOCALS_GREG(x)	(EH_LOCALS_GREGS + (SIZEOF_GREG_T * (x)))
117628e3cbeSEdward Pilatowicz #define	EH_LOCALS_SYSRET	(EH_LOCALS_GREGS + SIZEOF_GREGSET_T)
118628e3cbeSEdward Pilatowicz #define	EH_LOCALS_SYSRET1	(EH_LOCALS_SYSRET)
119628e3cbeSEdward Pilatowicz #define	EH_LOCALS_SYSRET2	(EH_LOCALS_SYSRET + CPTRSIZE)
120628e3cbeSEdward Pilatowicz #define	EH_LOCALS_RVFLAG	(EH_LOCALS_SYSRET + SIZEOF_SYSRET_T)
121628e3cbeSEdward Pilatowicz #define	EH_LOCALS_END		(EH_LOCALS_RVFLAG + CPTRSIZE)
122628e3cbeSEdward Pilatowicz 
123628e3cbeSEdward Pilatowicz #if (EH_LOCALS_END != EH_LOCALS_END_TGT)
12480e2ca85S #error "brand_misc.h EH_LOCALS_* macros don't add up"
125628e3cbeSEdward Pilatowicz #endif /* (EH_LOCALS_END != EH_LOCALS_END_TGT) */
126628e3cbeSEdward Pilatowicz 
127628e3cbeSEdward Pilatowicz /*
12880e2ca85S  * The second parameter of each entry in the {BRAND}_sysent_table
129628e3cbeSEdward Pilatowicz  * contains the number of parameters and flags that describe the
13080e2ca85S  * syscall return value encoding.
13180e2ca85S  *
13280e2ca85S  * When declaring new syscall emulation functions, it is very important
13380e2ca85S  * to to set the proper RV_* flags in the brand_sysent_table.  Upon failure,
13480e2ca85S  * syscall emulation fuctions should return an errno value.  Upon success
13580e2ca85S  * syscall emulation functions should return 0 and set the sysret_t return
13680e2ca85S  * value parameters accordingly.
13780e2ca85S  *
13880e2ca85S  * There are five possible syscall macro wrappers used in the kernel's system
13980e2ca85S  * call sysent table.  These turn into the following return values:
14080e2ca85S  *	SYSENT_CL	-> SYSENT_C or SYSENT_CI
14180e2ca85S  *	SYSENT_C	SE_64RVAL		RV_DEFAULT
14280e2ca85S  *	SYSENT_CI	SE_32RVAL1		RV_DEFAULT
14380e2ca85S  *	SYSENT_2CI	SE_32RVAL1|SE_32RVAL2	RV_32RVAL2
14480e2ca85S  *	SYSENT_AP	SE_64RVAL		RV_64RVAL
14580e2ca85S  *
146628e3cbeSEdward Pilatowicz  */
147628e3cbeSEdward Pilatowicz #define	NARGS_MASK	0x000000FF	/* Mask for syscalls argument count */
148628e3cbeSEdward Pilatowicz #define	RV_MASK		0x0000FF00	/* Mask for return value flags */
149628e3cbeSEdward Pilatowicz #define	RV_DEFAULT	0x00000100	/* syscall returns "default" values */
150628e3cbeSEdward Pilatowicz #define	RV_32RVAL2	0x00000200	/* syscall returns two 32-bit values */
151628e3cbeSEdward Pilatowicz #define	RV_64RVAL	0x00000400	/* syscall returns a 64-bit value */
152628e3cbeSEdward Pilatowicz 
153628e3cbeSEdward Pilatowicz #if !defined(_ASM)
154628e3cbeSEdward Pilatowicz 
155628e3cbeSEdward Pilatowicz /*
156628e3cbeSEdward Pilatowicz  * We define our own version of assert because the default one will
157628e3cbeSEdward Pilatowicz  * try to emit a localized message.  That is bad because first, we can't
158628e3cbeSEdward Pilatowicz  * emit messages to random file descriptors, and second localizing a message
159628e3cbeSEdward Pilatowicz  * requires allocating memory and we can't do that either.
160628e3cbeSEdward Pilatowicz  */
16180e2ca85S #define	brand_assert(ex)	(void)((ex) || \
16280e2ca85S 				(_brand_abort(0, #ex, __FILE__, __LINE__), 0))
16380e2ca85S #define	brand_abort(err, msg)	_brand_abort((err), (msg), __FILE__, __LINE__)
164*c3232c95SToomas Soome #define	EMULATE(cb, args)	{ (sysent_cb_t)(uintptr_t)(cb), (args) }
16580e2ca85S #define	NOSYS			EMULATE(brand_unimpl, (0 | RV_DEFAULT))
16680e2ca85S 
16780e2ca85S typedef long (*sysent_cb_t)();
16880e2ca85S typedef struct brand_sysent_table {
16980e2ca85S 	sysent_cb_t	st_callc;
17080e2ca85S 	uintptr_t	st_args;
17180e2ca85S } brand_sysent_table_t;
17280e2ca85S 
17380e2ca85S /*
17480e2ca85S  * These macros invoke a brandsys subcommand, B_TRUSS_POINT, used to expose
17580e2ca85S  * a call to an interpositioned syscall that would have otherwise gone
17680e2ca85S  * unnoticed by truss(1) because the interpositioned system call did not call
17780e2ca85S  * any system calls before returning.
17880e2ca85S  */
17980e2ca85S #define	B_TRUSS_POINT_5(rval, syscall_num, err, a0, a1, a2, a3, a4) \
18080e2ca85S 	__systemcall(rval, SYS_brand + 1024, \
18180e2ca85S 	    B_TRUSS_POINT, (syscall_num), (err), (a0), (a1), (a2), (a3), \
18280e2ca85S 	    (a4))
18380e2ca85S 
18480e2ca85S #define	B_TRUSS_POINT_4(rval, syscall_num, err, a0, a1, a2, a3) \
18580e2ca85S 	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), (a3), 0)
18680e2ca85S 
18780e2ca85S #define	B_TRUSS_POINT_3(rval, syscall_num, err, a0, a1, a2) \
18880e2ca85S 	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), 0, 0)
18980e2ca85S 
19080e2ca85S #define	B_TRUSS_POINT_2(rval, syscall_num, err, a0, a1) \
19180e2ca85S 	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), 0, 0, 0)
19280e2ca85S 
19380e2ca85S #define	B_TRUSS_POINT_1(rval, syscall_num, err, a0) \
19480e2ca85S 	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), 0, 0, 0, 0)
19580e2ca85S 
19680e2ca85S #define	B_TRUSS_POINT_0(rval, syscall_num, err) \
19780e2ca85S 	B_TRUSS_POINT_5(rval, (syscall_num), (err), 0, 0, 0, 0, 0)
198628e3cbeSEdward Pilatowicz 
199628e3cbeSEdward Pilatowicz /*
20080e2ca85S  * From runexe.s
201628e3cbeSEdward Pilatowicz  */
20280e2ca85S extern void brand_runexe(void *, ulong_t);
203628e3cbeSEdward Pilatowicz 
204628e3cbeSEdward Pilatowicz /*
20580e2ca85S  * From handler.s
206628e3cbeSEdward Pilatowicz  */
20780e2ca85S extern void brand_handler_table(void);
20880e2ca85S extern void brand_handler(void);
20980e2ca85S extern void brand_error(void);
21080e2ca85S extern void brand_success(void);
211628e3cbeSEdward Pilatowicz 
212628e3cbeSEdward Pilatowicz /*
21380e2ca85S  * From brand_util.c
214628e3cbeSEdward Pilatowicz  */
21580e2ca85S extern long brand_unimpl(sysret_t *rv, uintptr_t p1);
21680e2ca85S extern void _brand_abort(int, const char *, const char *, int);
21780e2ca85S extern int brand_uucopy(const void *, void *, size_t);
21880e2ca85S extern int brand_uucopystr(const void *, void *, size_t);
21980e2ca85S extern void brand_pre_init();
22080e2ca85S extern ulong_t brand_post_init(int, int, char **, char **);
22180e2ca85S #if defined(__sparc) && !defined(__sparcv9)
22280e2ca85S extern long brand_indir(sysret_t *, int, uintptr_t, uintptr_t, uintptr_t,
22380e2ca85S 	uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
22480e2ca85S #endif /* __sparc && !__sparcv9 */
225628e3cbeSEdward Pilatowicz 
226628e3cbeSEdward Pilatowicz #endif	/* !_ASM */
227628e3cbeSEdward Pilatowicz 
228628e3cbeSEdward Pilatowicz #ifdef	__cplusplus
229628e3cbeSEdward Pilatowicz }
230628e3cbeSEdward Pilatowicz #endif
231628e3cbeSEdward Pilatowicz 
23280e2ca85S #endif	/* _BRAND_MISC_H */
233