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 29 extern "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)(cb), (args) } 165 #define NOSYS EMULATE(brand_unimpl, (0 | RV_DEFAULT)) 166 167 typedef long (*sysent_cb_t)(); 168 typedef 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 */ 202 extern void brand_runexe(void *, ulong_t); 203 204 /* 205 * From handler.s 206 */ 207 extern void brand_handler_table(void); 208 extern void brand_handler(void); 209 extern void brand_error(void); 210 extern void brand_success(void); 211 212 /* 213 * From brand_util.c 214 */ 215 extern long brand_unimpl(sysret_t *rv, uintptr_t p1); 216 extern void _brand_abort(int, const char *, const char *, int); 217 extern int brand_uucopy(const void *, void *, size_t); 218 extern int brand_uucopystr(const void *, void *, size_t); 219 extern void brand_pre_init(); 220 extern ulong_t brand_post_init(int, int, char **, char **); 221 #if defined(__sparc) && !defined(__sparcv9) 222 extern 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