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