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