xref: /titanic_41/usr/src/uts/i86pc/ml/syscall_asm.s (revision eb5a5c7888f20ad6fa4580e785308db395ef6dfc)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
59acbbeafSnn35248 * Common Development and Distribution License (the "License").
69acbbeafSnn35248 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*eb5a5c78SSurya Prakki * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate/*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
267c478bd9Sstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
277c478bd9Sstevel@tonic-gate/*	  All Rights Reserved					*/
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate/*	Copyright (c) 1987, 1988 Microsoft Corporation		*/
307c478bd9Sstevel@tonic-gate/*	  All Rights Reserved					*/
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
337c478bd9Sstevel@tonic-gate#include <sys/asm_misc.h>
347c478bd9Sstevel@tonic-gate#include <sys/regset.h>
357c478bd9Sstevel@tonic-gate#include <sys/psw.h>
367c478bd9Sstevel@tonic-gate#include <sys/x86_archext.h>
379acbbeafSnn35248#include <sys/machbrand.h>
38ae115bc7Smrj#include <sys/privregs.h>
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate#if defined(__lint)
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate#include <sys/types.h>
437c478bd9Sstevel@tonic-gate#include <sys/thread.h>
447c478bd9Sstevel@tonic-gate#include <sys/systm.h>
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate#else	/* __lint */
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate#include <sys/segments.h>
497c478bd9Sstevel@tonic-gate#include <sys/pcb.h>
507c478bd9Sstevel@tonic-gate#include <sys/trap.h>
517c478bd9Sstevel@tonic-gate#include <sys/ftrace.h>
527c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
537c478bd9Sstevel@tonic-gate#include <sys/clock.h>
547c478bd9Sstevel@tonic-gate#include <sys/panic.h>
557c478bd9Sstevel@tonic-gate#include "assym.h"
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate#endif	/* __lint */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate/*
607c478bd9Sstevel@tonic-gate * We implement two flavours of system call entry points
617c478bd9Sstevel@tonic-gate *
627c478bd9Sstevel@tonic-gate * -	{int,lcall}/iret	(i386)
637c478bd9Sstevel@tonic-gate * -	sysenter/sysexit	(Pentium II and beyond)
647c478bd9Sstevel@tonic-gate *
657c478bd9Sstevel@tonic-gate * The basic pattern used in the handlers is to check to see if we can
667c478bd9Sstevel@tonic-gate * do fast (simple) version of the system call; if we can't we use various
677c478bd9Sstevel@tonic-gate * C routines that handle corner cases and debugging.
687c478bd9Sstevel@tonic-gate *
697c478bd9Sstevel@tonic-gate * To reduce the amount of assembler replication, yet keep the system call
707c478bd9Sstevel@tonic-gate * implementations vaguely comprehensible, the common code in the body
717c478bd9Sstevel@tonic-gate * of the handlers is broken up into a set of preprocessor definitions
727c478bd9Sstevel@tonic-gate * below.
737c478bd9Sstevel@tonic-gate */
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate/*
767c478bd9Sstevel@tonic-gate * When we have SYSCALLTRACE defined, we sneak an extra
777c478bd9Sstevel@tonic-gate * predicate into a couple of tests.
787c478bd9Sstevel@tonic-gate */
797c478bd9Sstevel@tonic-gate#if defined(SYSCALLTRACE)
807c478bd9Sstevel@tonic-gate#define	ORL_SYSCALLTRACE(r32)	\
817c478bd9Sstevel@tonic-gate	orl	syscalltrace, r32
827c478bd9Sstevel@tonic-gate#else
837c478bd9Sstevel@tonic-gate#define	ORL_SYSCALLTRACE(r32)
847c478bd9Sstevel@tonic-gate#endif
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate/*
877c478bd9Sstevel@tonic-gate * This check is false whenever we want to go fast i.e.
887c478bd9Sstevel@tonic-gate *
897c478bd9Sstevel@tonic-gate *	if (code >= NSYSCALL ||
907c478bd9Sstevel@tonic-gate *	    t->t_pre_sys || (t->t_proc_flag & TP_WATCHPT) != 0)
917c478bd9Sstevel@tonic-gate *		do full version
927c478bd9Sstevel@tonic-gate * #ifdef SYSCALLTRACE
937c478bd9Sstevel@tonic-gate *	if (syscalltrace)
947c478bd9Sstevel@tonic-gate *		do full version
957c478bd9Sstevel@tonic-gate * #endif
967c478bd9Sstevel@tonic-gate *
977c478bd9Sstevel@tonic-gate * Preconditions:
987c478bd9Sstevel@tonic-gate * -	t	curthread
997c478bd9Sstevel@tonic-gate * -	code	contains the syscall number
1007c478bd9Sstevel@tonic-gate * Postconditions:
1017c478bd9Sstevel@tonic-gate * -	%ecx and %edi are smashed
1027c478bd9Sstevel@tonic-gate * -	condition code flag ZF is cleared if pre-sys is too complex
1037c478bd9Sstevel@tonic-gate */
1047c478bd9Sstevel@tonic-gate#define	CHECK_PRESYS_NE(t, code)		\
1057c478bd9Sstevel@tonic-gate	movzbl	T_PRE_SYS(t), %edi;		\
1067c478bd9Sstevel@tonic-gate	movzwl	T_PROC_FLAG(t), %ecx;		\
1077c478bd9Sstevel@tonic-gate	andl	$TP_WATCHPT, %ecx;		\
1087c478bd9Sstevel@tonic-gate	orl	%ecx, %edi;			\
1097c478bd9Sstevel@tonic-gate	cmpl	$NSYSCALL, code;		\
1107c478bd9Sstevel@tonic-gate	setae	%cl;				\
1117c478bd9Sstevel@tonic-gate	movzbl	%cl, %ecx;			\
1127c478bd9Sstevel@tonic-gate	orl	%ecx, %edi;			\
1137c478bd9Sstevel@tonic-gate	ORL_SYSCALLTRACE(%edi)
1147c478bd9Sstevel@tonic-gate
1159acbbeafSnn35248/*
11665488c97S * Check if a brand_mach_ops callback is defined for the specified callback_id
11706b6cf06S * type.  If so invoke it with the user's %gs value loaded and the following
11865488c97S * data on the stack:
1199acbbeafSnn35248 *	   --------------------------------------
12006b6cf06S *         | user's %ss                         |
12106b6cf06S *    |    | user's %esp                        |
12206b6cf06S *    |    | EFLAGS register                    |
12306b6cf06S *    |    | user's %cs                         |
12406b6cf06S *    |    | user's %eip (user return address)  |
12506b6cf06S *    |    | 'scratch space'			|
12606b6cf06S *    |    | user's %ebx			|
12706b6cf06S *    |    | user's %gs selector		|
12806b6cf06S *    v    | lwp pointer			|
1299acbbeafSnn35248 *         | callback wrapper return addr 	|
1309acbbeafSnn35248 *         --------------------------------------
1319acbbeafSnn35248 *
1329acbbeafSnn35248 * If the brand code returns, we assume that we are meant to execute the
1339acbbeafSnn35248 * normal system call path.
13406b6cf06S *
13506b6cf06S * The interface to the brand callbacks on the 32-bit kernel assumes %ebx
13606b6cf06S * is available as a scratch register within the callback.  If the callback
13706b6cf06S * returns within the kernel then this macro will restore %ebx.  If the
13806b6cf06S * callback is going to return directly to userland then it should restore
13906b6cf06S * %ebx before returning to userland.
1409acbbeafSnn35248 */
1419acbbeafSnn35248#define	BRAND_CALLBACK(callback_id)					    \
1429acbbeafSnn35248	subl	$4, %esp		/* save some scratch space	*/ ;\
1439acbbeafSnn35248	pushl	%ebx			/* save %ebx to use for scratch	*/ ;\
1449acbbeafSnn35248	pushl	%gs			/* save the user %gs		*/ ;\
1459acbbeafSnn35248	movl	$KGS_SEL, %ebx						   ;\
1465f8e1617Snn35248	movw	%bx, %gs		/* switch to the kernel's %gs	*/ ;\
1479acbbeafSnn35248	movl	%gs:CPU_THREAD, %ebx	/* load the thread pointer	*/ ;\
1489acbbeafSnn35248	movl	T_LWP(%ebx), %ebx	/* load the lwp pointer		*/ ;\
149c7cf3afeSsp92102	pushl	%ebx			/* push the lwp pointer		*/ ;\
1509acbbeafSnn35248	movl	LWP_PROCP(%ebx), %ebx	/* load the proc pointer	*/ ;\
1519acbbeafSnn35248	movl	P_BRAND(%ebx), %ebx	/* load the brand pointer	*/ ;\
1529acbbeafSnn35248	movl	B_MACHOPS(%ebx), %ebx	/* load the machops pointer	*/ ;\
1539acbbeafSnn35248	movl	_CONST(_MUL(callback_id, CPTRSIZE))(%ebx), %ebx		   ;\
1549acbbeafSnn35248	cmpl	$0, %ebx						   ;\
1559acbbeafSnn35248	je	1f							   ;\
15606b6cf06S	movl	%ebx, 12(%esp)		/* save callback to scratch	*/ ;\
15706b6cf06S	movl	4(%esp), %ebx		/* grab the user %gs		*/ ;\
1585f8e1617Snn35248	movw	%bx, %gs		/* restore the user %gs		*/ ;\
15906b6cf06S	call	*12(%esp)		/* call callback in scratch	*/ ;\
16006b6cf06S1:	movl	4(%esp), %ebx		/* restore user %gs (re-do if	*/ ;\
16106b6cf06S	movw	%bx, %gs		/* branch due to no callback)	*/ ;\
16206b6cf06S	movl	8(%esp), %ebx		/* restore user's %ebx		*/ ;\
16306b6cf06S	addl	$16, %esp		/* restore stack ptr		*/
1649acbbeafSnn35248
1657c478bd9Sstevel@tonic-gate#define	MSTATE_TRANSITION(from, to)		\
1667c478bd9Sstevel@tonic-gate	pushl	$to;				\
1677c478bd9Sstevel@tonic-gate	pushl	$from;				\
1687c478bd9Sstevel@tonic-gate	call	syscall_mstate;			\
1697c478bd9Sstevel@tonic-gate	addl	$0x8, %esp
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate/*
1727c478bd9Sstevel@tonic-gate * aka CPU_STATS_ADDQ(CPU, sys.syscall, 1)
1737c478bd9Sstevel@tonic-gate * This must be called with interrupts or preemption disabled.
1747c478bd9Sstevel@tonic-gate */
1757c478bd9Sstevel@tonic-gate#define	CPU_STATS_SYS_SYSCALL_INC			\
1767c478bd9Sstevel@tonic-gate	addl	$1, %gs:CPU_STATS_SYS_SYSCALL;		\
1777c478bd9Sstevel@tonic-gate	adcl	$0, %gs:CPU_STATS_SYS_SYSCALL+4;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate#if !defined(__lint)
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate/*
1827c478bd9Sstevel@tonic-gate * ASSERT(lwptoregs(lwp) == rp);
1837c478bd9Sstevel@tonic-gate *
1847c478bd9Sstevel@tonic-gate * this may seem obvious, but very odd things happen if this
1857c478bd9Sstevel@tonic-gate * assertion is false
1867c478bd9Sstevel@tonic-gate *
1877c478bd9Sstevel@tonic-gate * Preconditions:
1887c478bd9Sstevel@tonic-gate *	-none-
1897c478bd9Sstevel@tonic-gate * Postconditions (if assertion is true):
1907c478bd9Sstevel@tonic-gate *	%esi and %edi are smashed
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate#if defined(DEBUG)
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate__lwptoregs_msg:
195613b2871SRichard Bean	.string	"syscall_asm.s:%d lwptoregs(%p) [%p] != rp [%p]"
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate#define	ASSERT_LWPTOREGS(t, rp)				\
1987c478bd9Sstevel@tonic-gate	movl	T_LWP(t), %esi;				\
1997c478bd9Sstevel@tonic-gate	movl	LWP_REGS(%esi), %edi;			\
2007c478bd9Sstevel@tonic-gate	cmpl	rp, %edi;				\
2017c478bd9Sstevel@tonic-gate	je	7f;					\
2027c478bd9Sstevel@tonic-gate	pushl	rp;					\
2037c478bd9Sstevel@tonic-gate	pushl	%edi;					\
2047c478bd9Sstevel@tonic-gate	pushl	%esi;					\
2057c478bd9Sstevel@tonic-gate	pushl	$__LINE__;				\
2067c478bd9Sstevel@tonic-gate	pushl	$__lwptoregs_msg;			\
2077c478bd9Sstevel@tonic-gate	call	panic;					\
2087c478bd9Sstevel@tonic-gate7:
2097c478bd9Sstevel@tonic-gate#else
2107c478bd9Sstevel@tonic-gate#define	ASSERT_LWPTOREGS(t, rp)
2117c478bd9Sstevel@tonic-gate#endif
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate#endif	/* __lint */
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate/*
2167c478bd9Sstevel@tonic-gate * This is an assembler version of this fragment:
2177c478bd9Sstevel@tonic-gate *
2187c478bd9Sstevel@tonic-gate * lwp->lwp_state = LWP_SYS;
2197c478bd9Sstevel@tonic-gate * lwp->lwp_ru.sysc++;
2207c478bd9Sstevel@tonic-gate * lwp->lwp_eosys = NORMALRETURN;
2217c478bd9Sstevel@tonic-gate * lwp->lwp_ap = argp;
2227c478bd9Sstevel@tonic-gate *
2237c478bd9Sstevel@tonic-gate * Preconditions:
2247c478bd9Sstevel@tonic-gate *	-none-
2257c478bd9Sstevel@tonic-gate * Postconditions:
2267c478bd9Sstevel@tonic-gate *	-none-
2277c478bd9Sstevel@tonic-gate */
2287c478bd9Sstevel@tonic-gate#define	SET_LWP(lwp, argp)				\
2297c478bd9Sstevel@tonic-gate	movb	$LWP_SYS, LWP_STATE(lwp);		\
2307c478bd9Sstevel@tonic-gate	addl	$1, LWP_RU_SYSC(lwp);			\
2317c478bd9Sstevel@tonic-gate	adcl	$0, LWP_RU_SYSC+4(lwp);			\
2327c478bd9Sstevel@tonic-gate	movb	$NORMALRETURN, LWP_EOSYS(lwp);		\
2337c478bd9Sstevel@tonic-gate	movl	argp, LWP_AP(lwp)
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate/*
2367c478bd9Sstevel@tonic-gate * Set up the thread, lwp, find the handler, and copy
2377c478bd9Sstevel@tonic-gate * in the arguments from userland to the kernel stack.
2387c478bd9Sstevel@tonic-gate *
2397c478bd9Sstevel@tonic-gate * Preconditions:
2407c478bd9Sstevel@tonic-gate * -	%eax contains the syscall number
2417c478bd9Sstevel@tonic-gate * Postconditions:
2427c478bd9Sstevel@tonic-gate * -	%eax contains a pointer to the sysent structure
2437c478bd9Sstevel@tonic-gate * -	%ecx is zeroed
2447c478bd9Sstevel@tonic-gate * -	%esi, %edi are smashed
2457c478bd9Sstevel@tonic-gate * -	%esp is SYS_DROPped ready for the syscall
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate#define	SIMPLE_SYSCALL_PRESYS(t, faultlabel)		\
2487c478bd9Sstevel@tonic-gate	movl	T_LWP(t), %esi;				\
2497c478bd9Sstevel@tonic-gate	movw	%ax, T_SYSNUM(t);			\
2507c478bd9Sstevel@tonic-gate	subl	$SYS_DROP, %esp;			\
2517c478bd9Sstevel@tonic-gate	shll	$SYSENT_SIZE_SHIFT, %eax;			\
2527c478bd9Sstevel@tonic-gate	SET_LWP(%esi, %esp);				\
2537c478bd9Sstevel@tonic-gate	leal	sysent(%eax), %eax;			\
2547c478bd9Sstevel@tonic-gate	movzbl	SY_NARG(%eax), %ecx;			\
2557c478bd9Sstevel@tonic-gate	testl	%ecx, %ecx;				\
2567c478bd9Sstevel@tonic-gate	jz	4f;					\
2577c478bd9Sstevel@tonic-gate	movl	%esp, %edi;				\
2587c478bd9Sstevel@tonic-gate	movl	SYS_DROP + REGOFF_UESP(%esp), %esi;	\
2597c478bd9Sstevel@tonic-gate	movl	$faultlabel, T_LOFAULT(t);		\
2607c478bd9Sstevel@tonic-gate	addl	$4, %esi;				\
2617c478bd9Sstevel@tonic-gate	rep;						\
2627c478bd9Sstevel@tonic-gate	  smovl;					\
2637c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(t);			\
2647c478bd9Sstevel@tonic-gate4:
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate/*
2677c478bd9Sstevel@tonic-gate * Check to see if a simple return is possible i.e.
2687c478bd9Sstevel@tonic-gate *
2697c478bd9Sstevel@tonic-gate *	if ((t->t_post_sys_ast | syscalltrace) != 0)
2707c478bd9Sstevel@tonic-gate *		do full version;
2717c478bd9Sstevel@tonic-gate *
2727c478bd9Sstevel@tonic-gate * Preconditions:
2737c478bd9Sstevel@tonic-gate * -	t is curthread
2747c478bd9Sstevel@tonic-gate * Postconditions:
2757c478bd9Sstevel@tonic-gate * -	condition code NE is set if post-sys is too complex
2767c478bd9Sstevel@tonic-gate * -	rtmp is zeroed if it isn't (we rely on this!)
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate#define	CHECK_POSTSYS_NE(t, rtmp)			\
2797c478bd9Sstevel@tonic-gate	xorl	rtmp, rtmp;				\
2807c478bd9Sstevel@tonic-gate	ORL_SYSCALLTRACE(rtmp);				\
2817c478bd9Sstevel@tonic-gate	orl	T_POST_SYS_AST(t), rtmp;		\
2827c478bd9Sstevel@tonic-gate	cmpl	$0, rtmp
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate/*
2857c478bd9Sstevel@tonic-gate * Fix up the lwp, thread, and eflags for a successful return
2867c478bd9Sstevel@tonic-gate *
2877c478bd9Sstevel@tonic-gate * Preconditions:
2887c478bd9Sstevel@tonic-gate * -	zwreg contains zero
2897c478bd9Sstevel@tonic-gate * Postconditions:
2907c478bd9Sstevel@tonic-gate * -	%esp has been unSYS_DROPped
2917c478bd9Sstevel@tonic-gate * -	%esi is smashed (points to lwp)
2927c478bd9Sstevel@tonic-gate */
2937c478bd9Sstevel@tonic-gate#define	SIMPLE_SYSCALL_POSTSYS(t, zwreg)		\
2947c478bd9Sstevel@tonic-gate	movl	T_LWP(t), %esi;				\
2957c478bd9Sstevel@tonic-gate	addl	$SYS_DROP, %esp;			\
2967c478bd9Sstevel@tonic-gate	movw	zwreg, T_SYSNUM(t);			\
2977c478bd9Sstevel@tonic-gate	movb	$LWP_USER, LWP_STATE(%esi);		\
2987c478bd9Sstevel@tonic-gate	andb	$_CONST(0xffff - PS_C), REGOFF_EFL(%esp)
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate/*
3017c478bd9Sstevel@tonic-gate * System call handler.  This is the destination of both the call
3027c478bd9Sstevel@tonic-gate * gate (lcall 0x27) _and_ the interrupt gate (int 0x91). For our purposes,
3037c478bd9Sstevel@tonic-gate * there are two significant differences between an interrupt gate and a call
3047c478bd9Sstevel@tonic-gate * gate:
3057c478bd9Sstevel@tonic-gate *
3067c478bd9Sstevel@tonic-gate * 1) An interrupt gate runs the handler with interrupts disabled, whereas a
3077c478bd9Sstevel@tonic-gate * call gate runs the handler with whatever EFLAGS settings were in effect at
3087c478bd9Sstevel@tonic-gate * the time of the call.
3097c478bd9Sstevel@tonic-gate *
3107c478bd9Sstevel@tonic-gate * 2) An interrupt gate pushes the contents of the EFLAGS register at the time
3117c478bd9Sstevel@tonic-gate * of the interrupt onto the stack, whereas a call gate does not.
3127c478bd9Sstevel@tonic-gate *
3137c478bd9Sstevel@tonic-gate * Because we use the following code sequence to handle system calls made from
3147c478bd9Sstevel@tonic-gate * _both_ a call gate _and_ an interrupt gate, these two differences must be
3157c478bd9Sstevel@tonic-gate * respected. In regards to number 1) above, the handler must ensure that a sane
3167c478bd9Sstevel@tonic-gate * EFLAGS snapshot is stored on the stack so that when the kernel returns back
3177c478bd9Sstevel@tonic-gate * to the user via iret (which returns to user with the EFLAGS value saved on
3187c478bd9Sstevel@tonic-gate * the stack), interrupts are re-enabled.
3197c478bd9Sstevel@tonic-gate *
3207c478bd9Sstevel@tonic-gate * In regards to number 2) above, the handler must always put a current snapshot
3217c478bd9Sstevel@tonic-gate * of EFLAGS onto the stack in the appropriate place. If we came in via an
3227c478bd9Sstevel@tonic-gate * interrupt gate, we will be clobbering the EFLAGS value that was pushed by
3237c478bd9Sstevel@tonic-gate * the interrupt gate. This is OK, as the only bit that was changed by the
3247c478bd9Sstevel@tonic-gate * hardware was the IE (interrupt enable) bit, which for an interrupt gate is
3257c478bd9Sstevel@tonic-gate * now off. If we were to do nothing, the stack would contain an EFLAGS with
3267c478bd9Sstevel@tonic-gate * IE off, resulting in us eventually returning back to the user with interrupts
3277c478bd9Sstevel@tonic-gate * disabled. The solution is to turn on the IE bit in the EFLAGS value saved on
3287c478bd9Sstevel@tonic-gate * the stack.
3297c478bd9Sstevel@tonic-gate *
3307c478bd9Sstevel@tonic-gate * Another subtlety which deserves mention is the difference between the two
3317c478bd9Sstevel@tonic-gate * descriptors. The call gate descriptor is set to instruct the hardware to copy
3327c478bd9Sstevel@tonic-gate * one parameter from the user stack to the kernel stack, whereas the interrupt
3337c478bd9Sstevel@tonic-gate * gate descriptor doesn't use the parameter passing mechanism at all. The
3347c478bd9Sstevel@tonic-gate * kernel doesn't actually use the parameter that is copied by the hardware; the
3357c478bd9Sstevel@tonic-gate * only reason it does this is so that there is a space on the stack large
3367c478bd9Sstevel@tonic-gate * enough to hold an EFLAGS register value, which happens to be in the correct
3377c478bd9Sstevel@tonic-gate * place for use by iret when we go back to userland. How convenient.
3387c478bd9Sstevel@tonic-gate *
3397c478bd9Sstevel@tonic-gate * Stack frame description in syscall() and callees.
3407c478bd9Sstevel@tonic-gate *
3417c478bd9Sstevel@tonic-gate * |------------|
3427c478bd9Sstevel@tonic-gate * | regs	| +(8*4)+4	registers
3437c478bd9Sstevel@tonic-gate * |------------|
3447c478bd9Sstevel@tonic-gate * | 8 args	| <- %esp	MAXSYSARGS (currently 8) arguments
3457c478bd9Sstevel@tonic-gate * |------------|
3467c478bd9Sstevel@tonic-gate *
3477c478bd9Sstevel@tonic-gate */
3487c478bd9Sstevel@tonic-gate#define	SYS_DROP	_CONST(_MUL(MAXSYSARGS, 4))
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate#if defined(__lint)
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3537c478bd9Sstevel@tonic-gatevoid
3547c478bd9Sstevel@tonic-gatesys_call()
3557c478bd9Sstevel@tonic-gate{}
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gatevoid
3587c478bd9Sstevel@tonic-gate_allsyscalls()
3597c478bd9Sstevel@tonic-gate{}
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gatesize_t _allsyscalls_size;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate#else	/* __lint */
3647c478bd9Sstevel@tonic-gate
3659acbbeafSnn35248	ENTRY_NP2(brand_sys_call, _allsyscalls)
3669acbbeafSnn35248	BRAND_CALLBACK(BRAND_CB_SYSCALL)
3677c478bd9Sstevel@tonic-gate
3689acbbeafSnn35248	ALTENTRY(sys_call)
3697c478bd9Sstevel@tonic-gate	/ on entry	eax = system call number
3709acbbeafSnn35248
3717c478bd9Sstevel@tonic-gate	/ set up the stack to look as in reg.h
3727c478bd9Sstevel@tonic-gate	subl    $8, %esp        / pad the stack with ERRCODE and TRAPNO
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate	SYSCALL_PUSH
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
3777c478bd9Sstevel@tonic-gate	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_SYSCALL) / Uses labels "8" and "9"
3787c478bd9Sstevel@tonic-gate	TRACE_REGS(%edi, %esp, %ebx, %ecx)	/ Uses label "9"
3797c478bd9Sstevel@tonic-gate	pushl	%eax
3807c478bd9Sstevel@tonic-gate	TRACE_STAMP(%edi)		/ Clobbers %eax, %edx, uses "9"
3817c478bd9Sstevel@tonic-gate	popl	%eax
3827c478bd9Sstevel@tonic-gate	movl	%eax, TTR_SYSNUM(%edi)
3837c478bd9Sstevel@tonic-gate#endif
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate_watch_do_syscall:
3867c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
3877c478bd9Sstevel@tonic-gate
388ae115bc7Smrj	/ Interrupts may be enabled here, so we must make sure this thread
389ae115bc7Smrj	/ doesn't migrate off the CPU while it updates the CPU stats.
390ae115bc7Smrj	/
391ae115bc7Smrj	/ XXX This is only true if we got here via call gate thru the LDT for
392ae115bc7Smrj	/ old style syscalls. Perhaps this preempt++-- will go away soon?
393ae115bc7Smrj	movl	%gs:CPU_THREAD, %ebx
394ae115bc7Smrj	addb	$1, T_PREEMPT(%ebx)
395ae115bc7Smrj	CPU_STATS_SYS_SYSCALL_INC
396ae115bc7Smrj	subb	$1, T_PREEMPT(%ebx)
397ae115bc7Smrj
398ae115bc7Smrj	ENABLE_INTR_FLAGS
399ae115bc7Smrj
4007c478bd9Sstevel@tonic-gate	pushl	%eax				/ preserve across mstate call
4017c478bd9Sstevel@tonic-gate	MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM)
4027c478bd9Sstevel@tonic-gate	popl	%eax
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ebx
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate	ASSERT_LWPTOREGS(%ebx, %esp)
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate	CHECK_PRESYS_NE(%ebx, %eax)
4097c478bd9Sstevel@tonic-gate	jne	_full_syscall_presys
4107c478bd9Sstevel@tonic-gate	SIMPLE_SYSCALL_PRESYS(%ebx, _syscall_fault)
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate_syslcall_call:
4137c478bd9Sstevel@tonic-gate	call	*SY_CALLC(%eax)
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate_syslcall_done:
4167c478bd9Sstevel@tonic-gate	CHECK_POSTSYS_NE(%ebx, %ecx)
4177c478bd9Sstevel@tonic-gate	jne	_full_syscall_postsys
4187c478bd9Sstevel@tonic-gate	SIMPLE_SYSCALL_POSTSYS(%ebx, %cx)
4197c478bd9Sstevel@tonic-gate	movl	%eax, REGOFF_EAX(%esp)
4207c478bd9Sstevel@tonic-gate	movl	%edx, REGOFF_EDX(%esp)
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate	MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER)
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate	/
4257c478bd9Sstevel@tonic-gate	/ get back via iret
4267c478bd9Sstevel@tonic-gate	/
427ae115bc7Smrj	CLI(%edx)
428ae115bc7Smrj	jmp	sys_rtt_syscall
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate_full_syscall_presys:
4317c478bd9Sstevel@tonic-gate	movl	T_LWP(%ebx), %esi
4327c478bd9Sstevel@tonic-gate	subl	$SYS_DROP, %esp
4337c478bd9Sstevel@tonic-gate	movb	$LWP_SYS, LWP_STATE(%esi)
4347c478bd9Sstevel@tonic-gate	pushl	%esp
4357c478bd9Sstevel@tonic-gate	pushl	%ebx
4367c478bd9Sstevel@tonic-gate	call	syscall_entry
4377c478bd9Sstevel@tonic-gate	addl	$8, %esp
4387c478bd9Sstevel@tonic-gate	jmp	_syslcall_call
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate_full_syscall_postsys:
4417c478bd9Sstevel@tonic-gate	addl	$SYS_DROP, %esp
4427c478bd9Sstevel@tonic-gate	pushl	%edx
4437c478bd9Sstevel@tonic-gate	pushl	%eax
4447c478bd9Sstevel@tonic-gate	pushl	%ebx
4457c478bd9Sstevel@tonic-gate	call	syscall_exit
4467c478bd9Sstevel@tonic-gate	addl	$12, %esp
4477c478bd9Sstevel@tonic-gate	MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER)
448ae115bc7Smrj	jmp	_sys_rtt
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate_syscall_fault:
4517c478bd9Sstevel@tonic-gate	push	$0xe			/ EFAULT
4527c478bd9Sstevel@tonic-gate	call	set_errno
4537c478bd9Sstevel@tonic-gate	addl	$4, %esp
4547c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/ fake syscall_err()
4557c478bd9Sstevel@tonic-gate	xorl	%edx, %edx
4567c478bd9Sstevel@tonic-gate	jmp	_syslcall_done
4577c478bd9Sstevel@tonic-gate	SET_SIZE(sys_call)
4589acbbeafSnn35248	SET_SIZE(brand_sys_call)
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate#endif	/* __lint */
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate/*
4637c478bd9Sstevel@tonic-gate * System call handler via the sysenter instruction
4647c478bd9Sstevel@tonic-gate *
4657c478bd9Sstevel@tonic-gate * Here's how syscall entry usually works (see sys_call for details).
4667c478bd9Sstevel@tonic-gate *
4677c478bd9Sstevel@tonic-gate * There, the caller (lcall or int) in userland has arranged that:
4687c478bd9Sstevel@tonic-gate *
4697c478bd9Sstevel@tonic-gate * -	%eax contains the syscall number
4707c478bd9Sstevel@tonic-gate * -	the user stack contains the args to the syscall
4717c478bd9Sstevel@tonic-gate *
4727c478bd9Sstevel@tonic-gate * Normally the lcall instruction into the call gate causes the processor
4737c478bd9Sstevel@tonic-gate * to push %ss, %esp, <top-of-stack>, %cs, %eip onto the kernel stack.
4747c478bd9Sstevel@tonic-gate * The sys_call handler then leaves space for r_trapno and r_err, and
4757c478bd9Sstevel@tonic-gate * pusha's {%eax, %ecx, %edx, %ebx, %esp, %ebp, %esi, %edi}, followed
4767c478bd9Sstevel@tonic-gate * by %ds, %es, %fs and %gs to capture a 'struct regs' on the stack.
4777c478bd9Sstevel@tonic-gate * Then the kernel sets %ds, %es and %gs to kernel selectors, and finally
4787c478bd9Sstevel@tonic-gate * extracts %efl and puts it into r_efl (which happens to live at the offset
4797c478bd9Sstevel@tonic-gate * that <top-of-stack> was copied into). Note that the value in r_efl has
4807c478bd9Sstevel@tonic-gate * the IF (interrupt enable) flag turned on. (The int instruction into the
4817c478bd9Sstevel@tonic-gate * interrupt gate does essentially the same thing, only instead of
4827c478bd9Sstevel@tonic-gate * <top-of-stack> we get eflags - see comment above.)
4837c478bd9Sstevel@tonic-gate *
4847c478bd9Sstevel@tonic-gate * In the sysenter case, things are a lot more primitive.
4857c478bd9Sstevel@tonic-gate *
4867c478bd9Sstevel@tonic-gate * The caller in userland has arranged that:
4877c478bd9Sstevel@tonic-gate *
4887c478bd9Sstevel@tonic-gate * -	%eax contains the syscall number
4897c478bd9Sstevel@tonic-gate * -	%ecx contains the user %esp
4907c478bd9Sstevel@tonic-gate * -	%edx contains the return %eip
4917c478bd9Sstevel@tonic-gate * -	the user stack contains the args to the syscall
4927c478bd9Sstevel@tonic-gate *
4937c478bd9Sstevel@tonic-gate * e.g.
4947c478bd9Sstevel@tonic-gate *	<args on the stack>
4957c478bd9Sstevel@tonic-gate *	mov	$SYS_callnum, %eax
4967c478bd9Sstevel@tonic-gate *	mov	$1f, %edx	/ return %eip
4977c478bd9Sstevel@tonic-gate *	mov	%esp, %ecx	/ return %esp
4987c478bd9Sstevel@tonic-gate *	sysenter
4997c478bd9Sstevel@tonic-gate * 1:
5007c478bd9Sstevel@tonic-gate *
5017c478bd9Sstevel@tonic-gate * Hardware and (privileged) initialization code have arranged that by
5027c478bd9Sstevel@tonic-gate * the time the sysenter instructions completes:
5037c478bd9Sstevel@tonic-gate *
5047c478bd9Sstevel@tonic-gate * - %eip is pointing to sys_sysenter (below).
5057c478bd9Sstevel@tonic-gate * - %cs and %ss are set to kernel text and stack (data) selectors.
5067c478bd9Sstevel@tonic-gate * - %esp is pointing at the lwp's stack
5077c478bd9Sstevel@tonic-gate * - Interrupts have been disabled.
5087c478bd9Sstevel@tonic-gate *
5097c478bd9Sstevel@tonic-gate * The task for the sysenter handler is:
5107c478bd9Sstevel@tonic-gate *
5117c478bd9Sstevel@tonic-gate * -	recreate the same regs structure on the stack and the same
5127c478bd9Sstevel@tonic-gate *	kernel state as if we'd come in on an lcall
5137c478bd9Sstevel@tonic-gate * -	do the normal work of a syscall
5147c478bd9Sstevel@tonic-gate * -	execute the system call epilogue, use sysexit to return to userland.
5157c478bd9Sstevel@tonic-gate *
5167c478bd9Sstevel@tonic-gate * Note that we are unable to return both "rvals" to userland with this
5177c478bd9Sstevel@tonic-gate * call, as %edx is used by the sysexit instruction.
5189acbbeafSnn35248 *
5199acbbeafSnn35248 * One final complication in this routine is its interaction with
5209acbbeafSnn35248 * single-stepping in a debugger.  For most of the system call mechanisms,
5219acbbeafSnn35248 * the CPU automatically clears the single-step flag before we enter the
5229acbbeafSnn35248 * kernel.  The sysenter mechanism does not clear the flag, so a user
5239acbbeafSnn35248 * single-stepping through a libc routine may suddenly find him/herself
5249acbbeafSnn35248 * single-stepping through the kernel.  To detect this, kmdb compares the
5259acbbeafSnn35248 * trap %pc to the [brand_]sys_enter addresses on each single-step trap.
5269acbbeafSnn35248 * If it finds that we have single-stepped to a sysenter entry point, it
5279acbbeafSnn35248 * explicitly clears the flag and executes the sys_sysenter routine.
5289acbbeafSnn35248 *
5299acbbeafSnn35248 * One final complication in this final complication is the fact that we
5309acbbeafSnn35248 * have two different entry points for sysenter: brand_sys_sysenter and
5319acbbeafSnn35248 * sys_sysenter.  If we enter at brand_sys_sysenter and start single-stepping
5329acbbeafSnn35248 * through the kernel with kmdb, we will eventually hit the instruction at
5339acbbeafSnn35248 * sys_sysenter.  kmdb cannot distinguish between that valid single-step
5349acbbeafSnn35248 * and the undesirable one mentioned above.  To avoid this situation, we
5359acbbeafSnn35248 * simply add a jump over the instruction at sys_sysenter to make it
5369acbbeafSnn35248 * impossible to single-step to it.
5377c478bd9Sstevel@tonic-gate */
5387c478bd9Sstevel@tonic-gate#if defined(__lint)
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gatevoid
5417c478bd9Sstevel@tonic-gatesys_sysenter()
5427c478bd9Sstevel@tonic-gate{}
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate#else	/* __lint */
5457c478bd9Sstevel@tonic-gate
5469acbbeafSnn35248	ENTRY_NP(brand_sys_sysenter)
5479acbbeafSnn35248	pushl	%edx
5489acbbeafSnn35248	BRAND_CALLBACK(BRAND_CB_SYSENTER)
5499acbbeafSnn35248	popl	%edx
5509acbbeafSnn35248	/*
5519acbbeafSnn35248	 * Jump over sys_sysenter to allow single-stepping as described
5529acbbeafSnn35248	 * above.
5539acbbeafSnn35248	 */
5549acbbeafSnn35248	ja	1f
5559acbbeafSnn35248
5569acbbeafSnn35248	ALTENTRY(sys_sysenter)
5579acbbeafSnn35248	nop
5589acbbeafSnn352481:
5597c478bd9Sstevel@tonic-gate	/
5607c478bd9Sstevel@tonic-gate	/ do what the call gate would've done to the stack ..
5617c478bd9Sstevel@tonic-gate	/
5627c478bd9Sstevel@tonic-gate	pushl	$UDS_SEL	/ (really %ss, but it's the same ..)
5637c478bd9Sstevel@tonic-gate	pushl	%ecx		/ userland makes this a copy of %esp
5647c478bd9Sstevel@tonic-gate	pushfl
5657c478bd9Sstevel@tonic-gate	orl	$PS_IE, (%esp)	/ turn interrupts on when we return to user
5667c478bd9Sstevel@tonic-gate	pushl	$UCS_SEL
5677c478bd9Sstevel@tonic-gate	pushl	%edx		/ userland makes this a copy of %eip
5687c478bd9Sstevel@tonic-gate	/
5697c478bd9Sstevel@tonic-gate	/ done.  finish building the stack frame
5707c478bd9Sstevel@tonic-gate	/
5717c478bd9Sstevel@tonic-gate	subl	$8, %esp	/ leave space for ERR and TRAPNO
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate	SYSENTER_PUSH
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
5767c478bd9Sstevel@tonic-gate	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_SYSENTER)	/ uses labels 8 and 9
5777c478bd9Sstevel@tonic-gate	TRACE_REGS(%edi, %esp, %ebx, %ecx)		/ uses label 9
5787c478bd9Sstevel@tonic-gate	pushl	%eax
5797c478bd9Sstevel@tonic-gate	TRACE_STAMP(%edi)		/ clobbers %eax, %edx, uses label 9
5807c478bd9Sstevel@tonic-gate	popl	%eax
5817c478bd9Sstevel@tonic-gate	movl	%eax, TTR_SYSNUM(%edi)
5827c478bd9Sstevel@tonic-gate#endif
5837c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate	CPU_STATS_SYS_SYSCALL_INC
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate	ENABLE_INTR_FLAGS
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate	pushl	%eax				/ preserve across mstate call
5907c478bd9Sstevel@tonic-gate	MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM)
5917c478bd9Sstevel@tonic-gate	popl	%eax
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ebx
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate	ASSERT_LWPTOREGS(%ebx, %esp)
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate	CHECK_PRESYS_NE(%ebx, %eax)
5987c478bd9Sstevel@tonic-gate	jne	_full_syscall_presys
5997c478bd9Sstevel@tonic-gate	SIMPLE_SYSCALL_PRESYS(%ebx, _syscall_fault)
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate_sysenter_call:
6027c478bd9Sstevel@tonic-gate	call	*SY_CALLC(%eax)
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate_sysenter_done:
6057c478bd9Sstevel@tonic-gate	CHECK_POSTSYS_NE(%ebx, %ecx)
6067c478bd9Sstevel@tonic-gate	jne	_full_syscall_postsys
6077c478bd9Sstevel@tonic-gate	SIMPLE_SYSCALL_POSTSYS(%ebx, %cx)
6087c478bd9Sstevel@tonic-gate	/
6097c478bd9Sstevel@tonic-gate	/ sysexit uses %edx to restore %eip, so we can't use it
6107c478bd9Sstevel@tonic-gate	/ to return a value, sigh.
6117c478bd9Sstevel@tonic-gate	/
6127c478bd9Sstevel@tonic-gate	movl	%eax, REGOFF_EAX(%esp)
6137c478bd9Sstevel@tonic-gate	/ movl	%edx, REGOFF_EDX(%esp)
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate	/ Interrupts will be turned on by the 'sti' executed just before
6167c478bd9Sstevel@tonic-gate	/ sysexit. The following ensures that restoring the user's EFLAGS
6177c478bd9Sstevel@tonic-gate	/ doesn't enable interrupts too soon.
6187c478bd9Sstevel@tonic-gate	andl	$_BITNOT(PS_IE), REGOFF_EFL(%esp)
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate	MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER)
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate	cli
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate	SYSCALL_POP
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate	popl	%edx			/ sysexit: %edx -> %eip
6277c478bd9Sstevel@tonic-gate	addl	$4, %esp		/ get CS off the stack
6287c478bd9Sstevel@tonic-gate	popfl				/ EFL
6297c478bd9Sstevel@tonic-gate	popl	%ecx			/ sysexit: %ecx -> %esp
6307c478bd9Sstevel@tonic-gate	sti
6317c478bd9Sstevel@tonic-gate	sysexit
6327c478bd9Sstevel@tonic-gate	SET_SIZE(sys_sysenter)
6339acbbeafSnn35248	SET_SIZE(brand_sys_sysenter)
6349acbbeafSnn35248
6357c478bd9Sstevel@tonic-gate/*
6367c478bd9Sstevel@tonic-gate * Declare a uintptr_t which covers the entire pc range of syscall
6377c478bd9Sstevel@tonic-gate * handlers for the stack walkers that need this.
6387c478bd9Sstevel@tonic-gate */
6397c478bd9Sstevel@tonic-gate	.align	CPTRSIZE
6407c478bd9Sstevel@tonic-gate	.globl	_allsyscalls_size
6417c478bd9Sstevel@tonic-gate	.type	_allsyscalls_size, @object
6427c478bd9Sstevel@tonic-gate_allsyscalls_size:
6437c478bd9Sstevel@tonic-gate	.NWORD	. - _allsyscalls
6447c478bd9Sstevel@tonic-gate	SET_SIZE(_allsyscalls_size)
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate#endif	/* __lint */
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate/*
6497c478bd9Sstevel@tonic-gate * These are the thread context handlers for lwps using sysenter/sysexit.
6507c478bd9Sstevel@tonic-gate */
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate#if defined(__lint)
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate/*ARGSUSED*/
6557c478bd9Sstevel@tonic-gatevoid
6567c478bd9Sstevel@tonic-gatesep_save(void *ksp)
6577c478bd9Sstevel@tonic-gate{}
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate/*ARGSUSED*/
6607c478bd9Sstevel@tonic-gatevoid
6617c478bd9Sstevel@tonic-gatesep_restore(void *ksp)
6627c478bd9Sstevel@tonic-gate{}
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate#else	/* __lint */
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate	/*
6677c478bd9Sstevel@tonic-gate	 * setting this value to zero as we switch away causes the
6687c478bd9Sstevel@tonic-gate	 * stack-pointer-on-sysenter to be NULL, ensuring that we
6697c478bd9Sstevel@tonic-gate	 * don't silently corrupt another (preempted) thread stack
6707c478bd9Sstevel@tonic-gate	 * when running an lwp that (somehow) didn't get sep_restore'd
6717c478bd9Sstevel@tonic-gate	 */
6727c478bd9Sstevel@tonic-gate	ENTRY_NP(sep_save)
6737c478bd9Sstevel@tonic-gate	xorl	%edx, %edx
6747c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
6757c478bd9Sstevel@tonic-gate	movl	$MSR_INTC_SEP_ESP, %ecx
6767c478bd9Sstevel@tonic-gate	wrmsr
6777c478bd9Sstevel@tonic-gate	ret
6787c478bd9Sstevel@tonic-gate	SET_SIZE(sep_save)
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate	/*
6817c478bd9Sstevel@tonic-gate	 * Update the kernel stack pointer as we resume onto this cpu.
6827c478bd9Sstevel@tonic-gate	 */
6837c478bd9Sstevel@tonic-gate	ENTRY_NP(sep_restore)
6847c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax			/* per-lwp kernel sp */
6857c478bd9Sstevel@tonic-gate	xorl	%edx, %edx
6867c478bd9Sstevel@tonic-gate	movl	$MSR_INTC_SEP_ESP, %ecx
6877c478bd9Sstevel@tonic-gate	wrmsr
6887c478bd9Sstevel@tonic-gate	ret
6897c478bd9Sstevel@tonic-gate	SET_SIZE(sep_restore)
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate#endif	/* __lint */
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate/*
6947c478bd9Sstevel@tonic-gate * Call syscall().  Called from trap() on watchpoint at lcall 0,7
6957c478bd9Sstevel@tonic-gate */
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate#if defined(__lint)
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gatevoid
7007c478bd9Sstevel@tonic-gatewatch_syscall(void)
7017c478bd9Sstevel@tonic-gate{}
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate#else	/* __lint */
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate	ENTRY_NP(watch_syscall)
706ae115bc7Smrj	CLI(%eax)
7077c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ebx
7087c478bd9Sstevel@tonic-gate	movl	T_STACK(%ebx), %esp		/ switch to the thread stack
7097c478bd9Sstevel@tonic-gate	movl	REGOFF_EAX(%esp), %eax		/ recover original syscall#
7107c478bd9Sstevel@tonic-gate	jmp	_watch_do_syscall
7117c478bd9Sstevel@tonic-gate	SET_SIZE(watch_syscall)
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate#endif	/* __lint */
714