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