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