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 */