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) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2019 Joyent, Inc.
  24  */
  25 
  26 /*
  27  * This is an assembly file that gets #include-ed into the brand-specific
  28  * assembly files (e.g. sn1_brand_asm.s) for Solaris-derived brands.
  29  * We can't make these into functions since in the trap context there's
  30  * no easy place to save the extra parameters that would be required, so
  31  * each brand module needs its own copy of this code.  We #include this and
  32  * use brand-specific #defines to replace the XXX_brand_... definitions.
  33  */ 
  34 
  35 #ifdef lint
  36 
  37 #include <sys/systm.h>
  38 
  39 #else /* !lint */
  40 
  41 #include <sys/asm_linkage.h>
  42 #include <sys/privregs.h>
  43 #include <sys/segments.h>
  44 #include "assym.h"
  45 #include "brand_asm.h"
  46 
  47 #endif  /* !lint */
  48 
  49 #ifdef  lint
  50 
  51 void
  52 XXX_brand_sysenter_callback(void)
  53 {
  54 }
  55 
  56 void
  57 XXX_brand_syscall_callback(void)
  58 {
  59 }
  60 
  61 #if defined(__amd64)
  62 void
  63 XXX_brand_syscall32_callback(void)
  64 {
  65 }
  66 #endif  /* amd64 */
  67 
  68 void
  69 XXX_brand_int91_callback(void)
  70 {
  71 }
  72 
  73 #else   /* !lint */
  74 
  75 #ifdef _ASM     /* The remainder of this file is only for assembly files */
  76 
  77 #if defined(__amd64)
  78 
  79 /*
  80  * syscall handler for 32-bit user processes:
  81  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
  82  * To 'return' to our user-space handler, we just need to place its address
  83  * into %rcx.  The original return address is passed back in SYSCALL_REG.
  84  */
  85 ENTRY(XXX_brand_syscall32_callback)
  86         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
  87             SCR_REG, SCR_REGB);
  88         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER);
  89         mov     %rcx, SYSCALL_REG; /* save orig return addr in syscall_reg */
  90         mov     SCR_REG, %rcx;  /* place new return addr in %rcx */
  91         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
  92         call    *x86_md_clear           /* Flush micro-arch state */
  93         mov     V_SSP(SP_REG), SP_REG   /* restore user stack pointer */
  94         jmp     nopop_sys_syscall32_swapgs_sysretl
  95 9:
  96         retq
  97 SET_SIZE(XXX_brand_syscall32_callback)
  98 
  99 /*
 100  * syscall handler for 64-bit user processes:
 101  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
 102  * To 'return' to our user-space handler, we just need to place its address
 103  * into %rcx.  The original return address is passed back in SYSCALL_REG.
 104  */
 105 ENTRY(XXX_brand_syscall_callback)
 106         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
 107             SCR_REG, SCR_REGB);
 108         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER);
 109         mov     %rcx, SYSCALL_REG; /* save orig return addr in syscall_reg */
 110         mov     SCR_REG, %rcx;  /* place new return addr in %rcx */
 111         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
 112         call    *x86_md_clear           /* Flush micro-arch state */
 113         mov     V_SSP(SP_REG), SP_REG   /* restore user stack pointer */
 114         jmp     nopop_sys_syscall_swapgs_sysretq
 115 9:
 116         retq
 117 SET_SIZE(XXX_brand_syscall_callback)
 118 
 119 /*
 120  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
 121  * To 'return' to our user-space handler, we just need to place its address
 122  * into %rdx.  The original return address is passed back in SYSCALL_REG.
 123  */
 124 ENTRY(XXX_brand_sysenter_callback)
 125         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
 126             SCR_REG, SCR_REGB);
 127         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER);
 128         mov     %rdx, SYSCALL_REG; /* save orig return addr in syscall_reg */
 129         mov     SCR_REG, %rdx;  /* place new return addr in %rdx */
 130         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
 131         mov     V_SSP(SP_REG), SP_REG   /* restore user stack pointer */
 132         jmp     sys_sysenter_swapgs_sysexit
 133 9:
 134         ret
 135 SET_SIZE(XXX_brand_sysenter_callback)
 136 
 137 /*
 138  * To 'return' to our user-space handler we need to update the user's %eip
 139  * pointer in the saved interrupt state on the stack.  The interrupt state was
 140  * pushed onto our stack automatically when the interrupt occured; see the
 141  * comments above.  The original return address is passed back in SYSCALL_REG.
 142  * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h.
 143  */
 144 ENTRY(XXX_brand_int91_callback)
 145         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
 146             SCR_REG, SCR_REGB);
 147         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); /* new ret addr is in scratch */
 148         mov     SCR_REG, SYSCALL_REG;   /* place new ret addr in syscallreg */
 149         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
 150         mov     V_SSP(SP_REG), SP_REG;  /* restore intr stack pointer */
 151         /*CSTYLED*/
 152         xchg    (SP_REG), SYSCALL_REG   /* swap new and orig. return addrs */
 153         jmp     sys_sysint_swapgs_iret
 154 9:
 155         retq
 156 SET_SIZE(XXX_brand_int91_callback)
 157 
 158 #else   /* !__amd64 */
 159 
 160 /*
 161  * To 'return' to our user-space handler, we need to replace the iret target
 162  * address.  The original return address is passed back in %eax.
 163  * See "32-BIT INTERPOSITION STACK" and "32-BIT INT STACK" in brand_asm.h.
 164  */
 165 ENTRY(XXX_brand_syscall_callback)
 166         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
 167             SCR_REG, SCR_REGB);
 168         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); /* new ret addr is in scratch */
 169         mov     SCR_REG, SYSCALL_REG;   /* place new ret addr in syscallreg */
 170         GET_V(SP_REG, 0, V_U_EBX, SCR_REG); /* restore scratch register */
 171         add     $V_END, SP_REG;         /* restore intr stack pointer */
 172         /*CSTYLED*/
 173         xchg    (SP_REG), SYSCALL_REG   /* swap new and orig. return addrs */
 174         jmp     nopop_sys_rtt_syscall
 175 9:
 176         ret
 177 SET_SIZE(XXX_brand_syscall_callback)
 178 
 179 /*
 180  * To 'return' to our user-space handler, we just need to place its address
 181  * into %edx.  The original return address is passed back in SYSCALL_REG.
 182  * See "32-BIT INTERPOSITION STACK" in brand_asm.h.
 183  */
 184 ENTRY(XXX_brand_sysenter_callback)
 185         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
 186             SCR_REG, SCR_REGB);
 187         mov     %edx, SCR_REG;  /* save orig return addr in scr reg */
 188         CALC_TABLE_ADDR(%edx, SPD_HANDLER); /* new return addr is in %edx */
 189         mov     SCR_REG, SYSCALL_REG;   /* save orig return addr in %eax */
 190         GET_V(SP_REG, 0, V_U_EBX, SCR_REG) /* restore scratch register */
 191         sysexit
 192 9:
 193         ret
 194 SET_SIZE(XXX_brand_sysenter_callback)
 195 
 196 #endif  /* !__amd64 */
 197 #endif  /* _ASM */
 198 #endif  /* !lint */