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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/asm_linkage.h> 29 #include <sys/regset.h> 30 #include <sys/segments.h> 31 #include <sys/syscall.h> 32 #include <sys/lx_brand.h> 33 34 #if defined(_ASM) 35 #include <sys/lx_signal.h> 36 #include <sys/lx_syscall.h> 37 #endif /* _ASM */ 38 39 #include "assym.h" 40 41 #define PIC_SETUP(r) \ 42 call 9f; \ 43 9: popl r; \ 44 addl $_GLOBAL_OFFSET_TABLE_ + [. - 9b], r 45 46 /* 47 * Each JMP must occupy 16 bytes 48 */ 49 #define JMP \ 50 pushl $_CONST(. - lx_handler_table); \ 51 jmp lx_handler; \ 52 .align 16; 53 54 #define JMP4 JMP; JMP; JMP; JMP 55 #define JMP16 JMP4; JMP4; JMP4; JMP4 56 #define JMP64 JMP16; JMP16; JMP16; JMP16 57 #define JMP256 JMP64; JMP64; JMP64; JMP64 58 59 /* 60 * Alternate jump table that turns on lx_traceflag before proceeding with 61 * the normal emulation routine. 62 */ 63 #define TJMP \ 64 pushl $_CONST(. - lx_handler_trace_table); \ 65 jmp lx_handler_trace; \ 66 .align 16; 67 68 #define TJMP4 TJMP; TJMP; TJMP; TJMP 69 #define TJMP16 TJMP4; TJMP4; TJMP4; TJMP4 70 #define TJMP64 TJMP16; TJMP16; TJMP16; TJMP16 71 #define TJMP256 TJMP64; TJMP64; TJMP64; TJMP64 72 73 74 #if defined(lint) 75 76 #include <sys/types.h> 77 #include <sys/regset.h> 78 #include <sys/signal.h> 79 80 void 81 lx_handler_table(void) 82 {} 83 84 void 85 lx_handler(void) 86 {} 87 88 /* ARGSUSED */ 89 void 90 lx_setup_clone(uintptr_t gs, void *retaddr, void *stk) 91 {} 92 93 /* ARGSUSED */ 94 void 95 lx_sigdeliver(int sig, siginfo_t *sip, void *p, size_t stacksz, 96 void (*stack_frame_builder)(void), void (*lx_sighandler)(void), 97 uintptr_t gs) 98 {} 99 100 /* ARGSUSED */ 101 void 102 lx_sigacthandler(int sig, siginfo_t *s, void *p) 103 {} 104 105 void 106 lx_sigreturn_tramp(void) 107 {} 108 109 void 110 lx_rt_sigreturn_tramp(void) 111 {} 112 113 /* ARGSUSED */ 114 void 115 lx_sigreturn_tolibc(uintptr_t sp) 116 {} 117 118 #else /* lint */ 119 120 /* 121 * On entry to this table, %eax will hold the return address. The 122 * location where we enter the table is a function of the system 123 * call number. The table needs the same alignment as the individual 124 * entries. 125 */ 126 .align 16 127 ENTRY_NP(lx_handler_trace_table) 128 TJMP256 129 TJMP64 130 SET_SIZE(lx_handler_trace_table) 131 132 .align 16 133 ENTRY_NP(lx_handler_table) 134 JMP256 135 JMP64 136 SET_SIZE(lx_handler_table) 137 138 ENTRY_NP(lx_handler_trace) 139 pushl %esi 140 PIC_SETUP(%esi) 141 movl lx_traceflag@GOT(%esi), %esi 142 movl $1, (%esi) 143 popl %esi 144 /* 145 * While we could just fall through to lx_handler(), we "tail-call" it 146 * instead to make ourselves a little more comprehensible to trace 147 * tools. 148 */ 149 jmp lx_handler 150 SET_SIZE(lx_handler_trace) 151 152 ALTENTRY(lx_handler) 153 /* 154 * %ebp isn't always going to be a frame pointer on Linux, but when 155 * it is, saving it here lets us have a coherent stack backtrace. 156 */ 157 pushl %ebp 158 159 /* 160 * Fill in a lx_regs_t structure on the stack. 161 */ 162 subl $SIZEOF_LX_REGS_T, %esp 163 164 /* 165 * Save %ebp and then fill it with what would be its usual value as 166 * the frame pointer. The value we save for %esp needs to be the 167 * stack pointer at the time of the interrupt so we need to skip the 168 * saved %ebp and (what will be) the return address. 169 */ 170 movl %ebp, LXR_EBP(%esp) 171 movl %esp, %ebp 172 addl $_CONST(SIZEOF_LX_REGS_T), %ebp 173 movl %ebp, LXR_ESP(%esp) 174 addl $_CONST(_MUL(CPTRSIZE, 2)), LXR_ESP(%esp) 175 176 movl $0, LXR_GS(%esp) 177 movw %gs, LXR_GS(%esp) 178 movl %edi, LXR_EDI(%esp) 179 movl %esi, LXR_ESI(%esp) 180 movl %ebx, LXR_EBX(%esp) 181 movl %edx, LXR_EDX(%esp) 182 movl %ecx, LXR_ECX(%esp) 183 movl %eax, LXR_EIP(%esp) 184 185 /* 186 * The kernel drops us into the middle of one of the tables above 187 * that then pushes that table offset onto the stack, and calls into 188 * lx_handler. That offset indicates the system call number while 189 * %eax holds the return address for the system call. We replace the 190 * value on the stack with the return address, and use the value to 191 * compute the system call number by dividing by the table entry size. 192 */ 193 xchgl CPTRSIZE(%ebp), %eax 194 shrl $4, %eax 195 movl %eax, LXR_EAX(%esp) 196 197 /* 198 * Switch to the Solaris libc's %gs. 199 */ 200 movl $LWPGS_SEL, %ebx 201 movw %bx, %gs 202 203 /* 204 * Call lx_emulate() whose only argument is a pointer to the 205 * lx_regs_t structure we've placed on the stack. 206 */ 207 pushl %esp 208 call lx_emulate 209 210 /* 211 * We use this global symbol to identify this return site when 212 * walking the stack backtrace. It needs to remain immediately 213 * after the call to lx_emulate(). 214 */ 215 ALTENTRY(lx_emulate_done) 216 217 /* 218 * Clean up the argument to lx_emulate(). 219 */ 220 addl $4, %esp 221 222 /* 223 * Restore the saved register state; we get %ebp, %esp and %esp from 224 * the ordinary locations rather than the saved state. 225 */ 226 movl LXR_EDI(%esp), %edi 227 movl LXR_ESI(%esp), %esi 228 movl LXR_EBX(%esp), %ebx 229 movl LXR_EDX(%esp), %edx 230 movl LXR_ECX(%esp), %ecx 231 movl LXR_EAX(%esp), %eax 232 movw LXR_GS(%esp), %gs 233 234 addl $SIZEOF_LX_REGS_T, %esp 235 236 movl %ebp, %esp 237 popl %ebp 238 ret 239 SET_SIZE(lx_handler) 240 241 ENTRY_NP(lx_swap_gs) 242 push %eax /* save the current eax value */ 243 movl 0xc(%esp),%eax /* 2nd param is a pointer */ 244 movw %gs,(%eax) /* use the pointer to save current gs */ 245 movl 0x8(%esp),%eax /* first parameter is the new gs value */ 246 movw %ax, %gs /* switch to the new gs value */ 247 pop %eax /* restore eax */ 248 ret 249 SET_SIZE(lx_swap_gs) 250 251 ENTRY_NP(lx_setup_clone) 252 xorl %ebp, %ebp /* terminating stack */ 253 popl %edx /* eat the start_clone() return address */ 254 popl %gs /* Switch back to the Linux libc's %gs */ 255 popl %edx /* Linux clone() return address */ 256 popl %esp /* New stack pointer */ 257 xorl %eax, %eax /* child returns 0 to SYS_clone() */ 258 jmp *%edx /* return to Linux app. */ 259 SET_SIZE(lx_setup_clone) 260 261 /* 262 * lx_sigdeliver(sig, siginfo_t *, ucontext_t *, stack_size, 263 * stack_build_routine, signal_handler, glibc_gs) 264 * 265 * This routine allocates stack space for the Linux signal stack, 266 * calls a routine to build the signal stack and then calls the Linux 267 * signal handler. This is written in assembly because of the way 268 * we need to directly manipulate the stack and pass the resulting 269 * stack to the signal handler with the Linux signal stack on top. 270 * 271 * When the Linux signal handler is called, the stack will look 272 * like this: 273 * 274 * ================================================= 275 * | Linux signal frame built by lx_stackbuilder() | 276 * ================================================= 277 * | LX_SIGRT_MAGIC | 278 * ================================================= 279 * | %ebp | 280 * ================================================= 281 */ 282 ENTRY_NP(lx_sigdeliver) 283 pushl %ebp 284 movl %esp, %ebp 285 movl 16(%ebp), %edx /* pointer to Solaris ucontext_t */ 286 pushl %edx /* save ucontext_t ptr for later */ 287 pushl $LX_SIGRT_MAGIC /* marker value for lx_(rt)_sigreturn */ 288 289 subl 20(%ebp), %esp /* create stack buffer */ 290 pushl %esp /* push stack pointer */ 291 pushl %edx /* push pointer to ucontext_t */ 292 pushl 12(%ebp) /* push pointer to siginfo_t */ 293 pushl 8(%ebp) /* push signal number */ 294 call *24(%ebp) /* lx_stackbuilder(sig, sip, ucp, sp) */ 295 add $16, %esp /* remove args from stack */ 296 movw 32(%ebp), %gs /* only low 16 bits are used */ 297 298 mov 4(%ebp),%eax /* fetch old %ebp from stack */ 299 mov 28(%ebp), %edx /* get address of Linux handler */ 300 mov %eax, %ebp /* restore old %ebp */ 301 jmp *%edx /* jmp to the Linux signal handler */ 302 SET_SIZE(lx_sigdeliver) 303 304 /* 305 * Due to the nature of signals, we need to be able to force the %gs 306 * value to that used by Solaris by running any Solaris code. 307 * 308 * This routine does that, then calls a C routine that will save the 309 * %gs value at the time of the signal off into a thread-specific data 310 * structure. Finally, we trampoline to the libc code that would 311 * normally interpose itself before calling a signal handler. 312 * 313 * The libc routine that calls user signal handlers ends with a 314 * setcontext, so we would never return here even if we used a call 315 * rather than a jmp. 316 * 317 * %esi is used for the PIC as it is guaranteed by the 386 ABI to 318 * survive the call to lx_sigsavegs. The downside is we must also 319 * preserve its value for our caller. 320 * 321 * Note that because lx_sigsavegs and libc_sigacthandler are externs, 322 * they need to be dereferenced via the GOT. 323 * 324 * IMPORTANT: Because libc apparently gets upset if extra data is 325 * left on its stack, this routine needs to be crafted 326 * in assembly so that the jmp to the libc interposer 327 * doesn't leave any cruft lying around. 328 */ 329 ENTRY_NP(lx_sigacthandler) 330 pushl %esi /* save %esi */ 331 pushl %gs /* push the Linux %gs */ 332 pushl $LWPGS_SEL 333 popl %gs /* install the Solaris %gs */ 334 335 PIC_SETUP(%esi) 336 movl lx_sigsavegs@GOT(%esi), %eax 337 call *%eax /* save the Linux %gs */ 338 movl libc_sigacthandler@GOT(%esi), %eax 339 add $4, %esp /* clear Linux %gs from stack */ 340 popl %esi /* restore %esi */ 341 jmp *(%eax) /* jmp to libc's interposer */ 342 SET_SIZE(lx_sigacthandler) 343 344 /* 345 * Trampoline code is called by the return at the end of a Linux 346 * signal handler to return control to the interrupted application 347 * via the lx_sigreturn() or lx_rt_sigreturn() syscalls. 348 * 349 * (lx_sigreturn() is called for legacy signal handling, and 350 * lx_rt_sigreturn() is called for "new"-style signals.) 351 * 352 * These two routines must consist of the EXACT code sequences below 353 * as gdb looks at the sequence of instructions a routine will return 354 * to determine whether it is in a signal handler or not. 355 */ 356 ENTRY_NP(lx_sigreturn_tramp) 357 popl %eax 358 movl $LX_SYS_sigreturn, %eax 359 int $0x80 360 SET_SIZE(lx_sigreturn_tramp) 361 362 ENTRY_NP(lx_rt_sigreturn_tramp) 363 movl $LX_SYS_rt_sigreturn, %eax 364 int $0x80 365 SET_SIZE(lx_rt_sigreturn_tramp) 366 367 /* 368 * Manipulate the stack in the way necessary for it to appear to libc 369 * that the signal handler it invoked via call_user_handler() is 370 * returning. 371 */ 372 ENTRY_NP(lx_sigreturn_tolibc) 373 movl 4(%esp), %esp /* set %esp to passed value */ 374 popl %ebp /* restore proper %ebp */ 375 ret /* return to libc interposer */ 376 SET_SIZE(lx_sigreturn_tolibc) 377 #endif /* lint */