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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25#ifndef _BRAND_MISC_H
26#define	_BRAND_MISC_H
27
28#ifdef	__cplusplus
29extern "C" {
30#endif
31
32/*
33 * This header file must uses _ASM defines to allow it to be included
34 * in assmebly source files
35 */
36#include <sys/asm_linkage.h>
37#include <sys/regset.h>
38#include <sys/syscall.h>
39#if !defined(_ASM)
40#include <sys/brand.h>
41#endif
42#include "assym.h"
43
44/*
45 * Our syscall emulation callback handler adds one argument to each
46 * system call, so we'll need to allocate space for one more argument
47 * above the maximum number of arguments that a system call can normally
48 * take.  Also, we assume that each syscall argument is a long, ie, we
49 * don't support long long syscall parameters.
50 */
51#if defined(__sparc)
52/*
53 * 32-bit and 64-bit sparc syscalls can take up to 8 arguments.
54 * 32-bit sparc indirect syscalls can take up to 9 arguments.
55 * Arguments 1 - 6 are passed via %o0 - %o5.
56 * Additional arguments are passed on the stack.
57 * So make space for 4 arguments on the stack.
58 */
59#define	EH_ARGS_COUNT		4
60#elif defined(__amd64)
61/*
62 * amd64 syscalls can take up to 8 arguments.
63 * Arguments 1 - 6 are passed via: %rdi, %rsi, %rdx, %r10, %r8, %r9
64 * Additional arguments are passed on the stack.
65 * So make space for 3 arguments on the stack.
66 */
67#define	EH_ARGS_COUNT		3
68#else /* !__sparc && !__amd64 */
69/*
70 * ia32 syscalls can take up to 8 arguments.
71 * All arguments are passed on the stack.
72 * So make space for 9 arguments on the stack.
73 */
74#define	EH_ARGS_COUNT		9
75#endif /* !__sparc && !__amd64 */
76
77
78#define	EH_ARGS_SIZE		(CPTRSIZE * EH_ARGS_COUNT)
79#define	EH_ARGS_OFFSET(x)	(STACK_BIAS + MINFRAME + (CPTRSIZE * (x)))
80#define	EH_LOCALS_SIZE		(EH_ARGS_SIZE + SIZEOF_GREGSET_T + \
81				    SIZEOF_SYSRET_T + CPTRSIZE)
82
83#if defined(__sparc)
84/*
85 * On sparc, all emulation callback handler variable access is done
86 * relative to %sp, so access offsets are positive.
87 */
88#define	EH_LOCALS_START		(STACK_BIAS + MINFRAME + EH_ARGS_SIZE)
89#define	EH_LOCALS_END_TGT	(STACK_BIAS + MINFRAME + EH_LOCALS_SIZE)
90#else /* !__sparc */
91/*
92 * On x86, all emulation callback handler variable access is done
93 * relative to %ebp/%rbp, so access offsets are negative.
94 */
95#define	EH_LOCALS_START		(-(EH_LOCALS_SIZE - \
96				    (STACK_BIAS + MINFRAME + EH_ARGS_SIZE)))
97#define	EH_LOCALS_END_TGT	0
98#endif /* !__sparc */
99
100/*
101 * In our emulation callback handler, our stack will look like:
102 *		-------------------------------------------------
103 *	  %bp   | long		rvflag				|
104 *	   |    | sysret_t	sysret				|
105 *	   v    | gregset_t	gregs				|
106 *	  %sp   | long		callback args[EH_ARGS_COUNT]	|
107 *		-------------------------------------------------
108 * For ia32, use %ebp and %esp instead of %bp and %sp.
109 * For amd64, use %rbp and %rsp instead of %bp and %sp.
110 *
111 * Our emulation callback handler always saves enough space to hold the
112 * maximum number of stack arguments to a system call.  This is architecture
113 * specific and is defined via EH_ARGS_COUNT.
114 */
115#define	EH_LOCALS_GREGS		(EH_LOCALS_START)
116#define	EH_LOCALS_GREG(x)	(EH_LOCALS_GREGS + (SIZEOF_GREG_T * (x)))
117#define	EH_LOCALS_SYSRET	(EH_LOCALS_GREGS + SIZEOF_GREGSET_T)
118#define	EH_LOCALS_SYSRET1	(EH_LOCALS_SYSRET)
119#define	EH_LOCALS_SYSRET2	(EH_LOCALS_SYSRET + CPTRSIZE)
120#define	EH_LOCALS_RVFLAG	(EH_LOCALS_SYSRET + SIZEOF_SYSRET_T)
121#define	EH_LOCALS_END		(EH_LOCALS_RVFLAG + CPTRSIZE)
122
123#if (EH_LOCALS_END != EH_LOCALS_END_TGT)
124#error "brand_misc.h EH_LOCALS_* macros don't add up"
125#endif /* (EH_LOCALS_END != EH_LOCALS_END_TGT) */
126
127/*
128 * The second parameter of each entry in the {BRAND}_sysent_table
129 * contains the number of parameters and flags that describe the
130 * syscall return value encoding.
131 *
132 * When declaring new syscall emulation functions, it is very important
133 * to to set the proper RV_* flags in the brand_sysent_table.  Upon failure,
134 * syscall emulation fuctions should return an errno value.  Upon success
135 * syscall emulation functions should return 0 and set the sysret_t return
136 * value parameters accordingly.
137 *
138 * There are five possible syscall macro wrappers used in the kernel's system
139 * call sysent table.  These turn into the following return values:
140 *	SYSENT_CL	-> SYSENT_C or SYSENT_CI
141 *	SYSENT_C	SE_64RVAL		RV_DEFAULT
142 *	SYSENT_CI	SE_32RVAL1		RV_DEFAULT
143 *	SYSENT_2CI	SE_32RVAL1|SE_32RVAL2	RV_32RVAL2
144 *	SYSENT_AP	SE_64RVAL		RV_64RVAL
145 *
146 */
147#define	NARGS_MASK	0x000000FF	/* Mask for syscalls argument count */
148#define	RV_MASK		0x0000FF00	/* Mask for return value flags */
149#define	RV_DEFAULT	0x00000100	/* syscall returns "default" values */
150#define	RV_32RVAL2	0x00000200	/* syscall returns two 32-bit values */
151#define	RV_64RVAL	0x00000400	/* syscall returns a 64-bit value */
152
153#if !defined(_ASM)
154
155/*
156 * We define our own version of assert because the default one will
157 * try to emit a localized message.  That is bad because first, we can't
158 * emit messages to random file descriptors, and second localizing a message
159 * requires allocating memory and we can't do that either.
160 */
161#define	brand_assert(ex)	(void)((ex) || \
162				(_brand_abort(0, #ex, __FILE__, __LINE__), 0))
163#define	brand_abort(err, msg)	_brand_abort((err), (msg), __FILE__, __LINE__)
164#define	EMULATE(cb, args)	{ (sysent_cb_t)(uintptr_t)(cb), (args) }
165#define	NOSYS			EMULATE(brand_unimpl, (0 | RV_DEFAULT))
166
167typedef long (*sysent_cb_t)();
168typedef struct brand_sysent_table {
169	sysent_cb_t	st_callc;
170	uintptr_t	st_args;
171} brand_sysent_table_t;
172
173/*
174 * These macros invoke a brandsys subcommand, B_TRUSS_POINT, used to expose
175 * a call to an interpositioned syscall that would have otherwise gone
176 * unnoticed by truss(1) because the interpositioned system call did not call
177 * any system calls before returning.
178 */
179#define	B_TRUSS_POINT_5(rval, syscall_num, err, a0, a1, a2, a3, a4) \
180	__systemcall(rval, SYS_brand + 1024, \
181	    B_TRUSS_POINT, (syscall_num), (err), (a0), (a1), (a2), (a3), \
182	    (a4))
183
184#define	B_TRUSS_POINT_4(rval, syscall_num, err, a0, a1, a2, a3) \
185	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), (a3), 0)
186
187#define	B_TRUSS_POINT_3(rval, syscall_num, err, a0, a1, a2) \
188	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), 0, 0)
189
190#define	B_TRUSS_POINT_2(rval, syscall_num, err, a0, a1) \
191	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), 0, 0, 0)
192
193#define	B_TRUSS_POINT_1(rval, syscall_num, err, a0) \
194	B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), 0, 0, 0, 0)
195
196#define	B_TRUSS_POINT_0(rval, syscall_num, err) \
197	B_TRUSS_POINT_5(rval, (syscall_num), (err), 0, 0, 0, 0, 0)
198
199/*
200 * From runexe.s
201 */
202extern void brand_runexe(void *, ulong_t);
203
204/*
205 * From handler.s
206 */
207extern void brand_handler_table(void);
208extern void brand_handler(void);
209extern void brand_error(void);
210extern void brand_success(void);
211
212/*
213 * From brand_util.c
214 */
215extern long brand_unimpl(sysret_t *rv, uintptr_t p1);
216extern void _brand_abort(int, const char *, const char *, int);
217extern int brand_uucopy(const void *, void *, size_t);
218extern int brand_uucopystr(const void *, void *, size_t);
219extern void brand_pre_init();
220extern ulong_t brand_post_init(int, int, char **, char **);
221#if defined(__sparc) && !defined(__sparcv9)
222extern long brand_indir(sysret_t *, int, uintptr_t, uintptr_t, uintptr_t,
223	uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
224#endif /* __sparc && !__sparcv9 */
225
226#endif	/* !_ASM */
227
228#ifdef	__cplusplus
229}
230#endif
231
232#endif	/* _BRAND_MISC_H */
233