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