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