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) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #ifndef _COMMON_BRAND_ASM_H 26 #define _COMMON_BRAND_ASM_H 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #ifndef lint 33 34 #include <sys/asm_linkage.h> 35 #include <sys/privregs.h> 36 #include <sys/segments.h> 37 #include "assym.h" 38 39 #endif /* lint */ 40 41 #ifdef _ASM /* The remainder of this file is only for assembly files */ 42 43 #if defined(__amd64) 44 /* 45 * Common to all 64-bit callbacks: 46 * 47 * We're running on the kernel's %gs. 48 * 49 * We return directly to userland, bypassing the _update_sregs logic, so 50 * the routine must NOT do anything that could cause a context switch. 51 * 52 * %rax - syscall number 53 * 54 * When called, all general registers, except for %r15, are as they were when 55 * the user process made the system call. %r15 is available to the callback as 56 * a scratch register. If the callback returns to the kernel path, %r15 does 57 * not have to be restored to the user value. If the callback returns to the 58 * userlevel emulation code, the callback should restore %r15 if the emulation 59 * depends on the original userlevel value. 60 * 61 * 64-BIT INTERPOSITION STACK 62 * On entry to the callback the stack looks like this: 63 * -------------------------------------- 64 * 32 | callback pointer | 65 * 24 | saved stack pointer | 66 * | 16 | lwp pointer | 67 * v 8 | user return address | 68 * 0 | BRAND_CALLBACK()'s return addr | 69 * -------------------------------------- 70 */ 71 72 #define V_COUNT 5 73 #define V_END (CLONGSIZE * 5) 74 #define V_SSP (CLONGSIZE * 3) 75 #define V_LWP (CLONGSIZE * 2) 76 #define V_URET_ADDR (CLONGSIZE * 1) 77 #define V_CB_ADDR (CLONGSIZE * 0) 78 79 #define SP_REG %rsp 80 #define SCR_REG %r15 81 #define SCR_REGB %r15b 82 #define SYSCALL_REG %rax 83 84 /* 85 * 64-BIT INT STACK 86 * For int callbacks (e.g. int91) the saved stack pointer (V_SSP) points at 87 * the state saved when we took the interrupt: 88 * -------------------------------------- 89 * | 32 | user's %ss | 90 * | 24 | user's %esp | 91 * | 16 | EFLAGS register | 92 * v 8 | user's %cs | 93 * 0 | user's %eip (user return address) | 94 * -------------------------------------- 95 */ 96 #define V_U_EIP (CLONGSIZE * 0) 97 98 #else /* !__amd64 */ 99 /* 100 * 32-BIT INTERPOSITION STACK 101 * When our syscall interposition callback entry point gets invoked the 102 * stack looks like this: 103 * -------------------------------------- 104 * | 16 | 'scratch space' | 105 * | 12 | user's %ebx | 106 * | 8 | user's %gs selector | 107 * v 4 | lwp pointer | 108 * 0 | callback wrapper return addr | 109 * -------------------------------------- 110 */ 111 112 #define V_COUNT 5 113 #define V_END (CLONGSIZE * 5) 114 #define V_U_EBX (CLONGSIZE * 3) 115 #define V_LWP (CLONGSIZE * 1) 116 #define V_CB_ADDR (CLONGSIZE * 0) 117 118 #define SP_REG %esp 119 #define SCR_REG %ebx 120 #define SCR_REGB %bl 121 #define SYSCALL_REG %eax 122 123 /* 124 * 32-BIT INT STACK 125 * For the lcall handler for 32-bit OS (i.e. xxx_brand_syscall_callback) 126 * above the stack contents common to all callbacks is the int/lcall-specific 127 * state: 128 * -------------------------------------- 129 * | 36 | user's %ss | 130 * | 32 | user's %esp | 131 * | 28 | EFLAGS register | 132 * v 24 | user's %cs | 133 * 20 | user's %eip (user return address) | 134 * -------------------------------------- 135 */ 136 #define V_U_EIP (V_END + (CLONGSIZE * 0)) 137 138 #endif /* !__amd64 */ 139 140 /* 141 * The following macros allow us to access to variables/parameters passed 142 * in on the stack. They take the following variables: 143 * sp - a register with the current stack pointer value 144 * pcnt - the number of words currently pushed onto the stack 145 * var - the variable to lookup 146 * reg - a register to read the variable into, or 147 * a register to write to the variable 148 */ 149 #define V_OFFSET(pcnt, var) \ 150 (var + (pcnt * CLONGSIZE)) 151 152 #define GET_V(sp, pcnt, var, reg) \ 153 mov V_OFFSET(pcnt, var)(sp), reg 154 155 #define SET_V(sp, pcnt, var, reg) \ 156 mov reg, V_OFFSET(pcnt, var)(sp) 157 158 #define GET_PROCP(sp, pcnt, reg) \ 159 GET_V(sp, pcnt, V_LWP, reg); /* get lwp pointer */ \ 160 mov LWP_PROCP(reg), reg /* get proc pointer */ 161 162 #define GET_P_BRAND_DATA(sp, pcnt, reg) \ 163 GET_PROCP(sp, pcnt, reg); \ 164 mov P_BRAND_DATA(reg), reg /* get p_brand_data */ 165 166 /* 167 * Each of the following macros returns to the standard syscall codepath if 168 * it detects that this process is not able, or intended, to emulate this 169 * system call. They all assume that the routine provides a 'bail-out' 170 * label of '9'. 171 */ 172 173 /* 174 * See if this process has a user-space handler registered for it. For the 175 * brand, the per-process brand data holds the address of the handler. 176 * As shown in the stack diagrams above, the callback code leaves the lwp 177 * pointer at well-defined offsets, so check if proc_data_t->X_handler is 178 * non-NULL. For each brand, the handler parameter refers to the brand's 179 * user-space handler variable name. 180 */ 181 #define CHECK_FOR_HANDLER(scr, handler) \ 182 GET_P_BRAND_DATA(SP_REG, 0, scr); /* get p_brand_data */ \ 183 cmp $0, scr; \ 184 je 9f; \ 185 cmp $0, handler(scr); /* check handler */ \ 186 je 9f 187 188 /* 189 * If the system call number is >= 1024, then it is coming from the 190 * emulation support library. As such we should handle it natively instead 191 * of sending it back to the emulation library. 192 */ 193 #define CHECK_FOR_NATIVE(reg) \ 194 cmp $1024, reg; \ 195 jl 1f; \ 196 sub $1024, reg; \ 197 jmp 9f; \ 198 1: 199 200 /* 201 * Check to see if we want to interpose on this system call. If not, we 202 * jump back into the normal syscall path and pretend nothing happened. 203 * This macro is usable for brands which have the same number of syscalls 204 * as the base OS. 205 */ 206 #define CHECK_FOR_INTERPOSITION(emul_table, call, scr, scr_low) \ 207 cmp $NSYSCALL, call; /* is 0 <= syscall <= MAX? */ \ 208 ja 9f; /* no, take normal ret path */ \ 209 lea emul_table, scr; \ 210 /*CSTYLED*/ \ 211 mov (scr), scr; \ 212 add call, scr; \ 213 /*CSTYLED*/ \ 214 movb (scr), scr_low; \ 215 cmpb $0, scr_low; \ 216 je 9f /* no, take normal ret path */ 217 218 #define CALLBACK_PROLOGUE(emul_table, handler, call, scr, scr_low) \ 219 CHECK_FOR_HANDLER(scr, handler); \ 220 CHECK_FOR_NATIVE(call); \ 221 CHECK_FOR_INTERPOSITION(emul_table, call, scr, scr_low) 222 223 /* 224 * Rather than returning to the instruction after the syscall, we need to 225 * transfer control into the brand library's handler table at 226 * table_addr + (16 * syscall_num), thus encoding the system call number in the 227 * instruction pointer. The CALC_TABLE_ADDR macro performs that calculation. 228 * 229 * This macro assumes the syscall number is in SYSCALL_REG and it clobbers 230 * that register. It leaves the calculated handler table return address in 231 * the scratch reg. 232 */ 233 #define CALC_TABLE_ADDR(scr, handler) \ 234 GET_P_BRAND_DATA(SP_REG, 0, scr); /* get p_brand_data ptr */ \ 235 mov handler(scr), scr; /* get p_brand_data->XX_handler */ \ 236 shl $4, SYSCALL_REG; /* syscall_num * 16 */ \ 237 add SYSCALL_REG, scr /* leave return addr in scr reg. */ 238 239 #endif /* _ASM */ 240 241 #ifdef __cplusplus 242 } 243 #endif 244 245 #endif /* _COMMON_BRAND_ASM_H */ 246