xref: /onnv-gate/usr/src/uts/sparc/v9/ml/syscall_trap.s (revision 11172:a792f425ae2e)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*11172SHaik.Aftandilian@Sun.COM * Common Development and Distribution License (the "License").
6*11172SHaik.Aftandilian@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate/*
22*11172SHaik.Aftandilian@Sun.COM * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate/*
270Sstevel@tonic-gate * System call trap handler.
280Sstevel@tonic-gate */
290Sstevel@tonic-gate#include <sys/asm_linkage.h>
300Sstevel@tonic-gate#include <sys/machpcb.h>
310Sstevel@tonic-gate#include <sys/machthread.h>
320Sstevel@tonic-gate#include <sys/syscall.h>
330Sstevel@tonic-gate#include <sys/trap.h>
340Sstevel@tonic-gate#include <sys/machtrap.h>
350Sstevel@tonic-gate#include <sys/pcb.h>
360Sstevel@tonic-gate#include <sys/machparam.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate#if !defined(lint) && !defined(__lint)
390Sstevel@tonic-gate#include "assym.h"
400Sstevel@tonic-gate#endif
410Sstevel@tonic-gate
420Sstevel@tonic-gate#ifdef TRAPTRACE
430Sstevel@tonic-gate#include <sys/traptrace.h>
440Sstevel@tonic-gate#endif /* TRAPTRACE */
450Sstevel@tonic-gate
460Sstevel@tonic-gate#if defined(lint) || defined(__lint)
470Sstevel@tonic-gate
480Sstevel@tonic-gate/*ARGSUSED*/
490Sstevel@tonic-gatevoid
500Sstevel@tonic-gatesyscall_trap(struct regs *rp)	/* for tags only; not called from C */
510Sstevel@tonic-gate{}
520Sstevel@tonic-gate
530Sstevel@tonic-gate#else /* lint */
540Sstevel@tonic-gate
550Sstevel@tonic-gate#if (1 << SYSENT_SHIFT) != SYSENT_SIZE
560Sstevel@tonic-gate#error	"SYSENT_SHIFT does not correspond to size of sysent structure"
570Sstevel@tonic-gate#endif
580Sstevel@tonic-gate
590Sstevel@tonic-gate/*
600Sstevel@tonic-gate * Native System call trap handler.
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * We branch here from sys_trap when a 64-bit system call occurs.
630Sstevel@tonic-gate *
640Sstevel@tonic-gate * Entry:
650Sstevel@tonic-gate *	%o0 = regs
660Sstevel@tonic-gate *
670Sstevel@tonic-gate * Usage:
680Sstevel@tonic-gate *	%l0 = saved return address
690Sstevel@tonic-gate *	%l1 = saved regs
700Sstevel@tonic-gate *	%l2 = lwp
710Sstevel@tonic-gate */
720Sstevel@tonic-gate	ENTRY_NP(syscall_trap)
730Sstevel@tonic-gate	ldn	[THREAD_REG + T_CPU], %g1	! get cpu pointer
740Sstevel@tonic-gate	mov	%o7, %l0			! save return addr
750Sstevel@tonic-gate	!
760Sstevel@tonic-gate	! If the trapping thread has the address mask bit set, then it's
770Sstevel@tonic-gate	!   a 32-bit process, and has no business calling 64-bit syscalls.
780Sstevel@tonic-gate	!
790Sstevel@tonic-gate	ldx	[%o0 + TSTATE_OFF], %l1		! saved %tstate.am is that
800Sstevel@tonic-gate	andcc	%l1, TSTATE_AM, %l1		!   of the trapping proc
810Sstevel@tonic-gate	bne,pn	%xcc, _syscall_ill		!
820Sstevel@tonic-gate	mov	%o0, %l1			! save reg pointer
830Sstevel@tonic-gate	mov	%i0, %o0			! copy 1st arg
840Sstevel@tonic-gate	mov	%i1, %o1			! copy 2nd arg
850Sstevel@tonic-gate	ldx	[%g1 + CPU_STATS_SYS_SYSCALL], %g2
860Sstevel@tonic-gate	inc	%g2				! cpu_stats.sys.syscall++
870Sstevel@tonic-gate	stx	%g2, [%g1 + CPU_STATS_SYS_SYSCALL]
880Sstevel@tonic-gate
890Sstevel@tonic-gate	!
900Sstevel@tonic-gate	! Set new state for LWP
910Sstevel@tonic-gate	!
920Sstevel@tonic-gate	ldn	[THREAD_REG + T_LWP], %l2
930Sstevel@tonic-gate	mov	LWP_SYS, %g3
940Sstevel@tonic-gate	mov	%i2, %o2			! copy 3rd arg
950Sstevel@tonic-gate	stb	%g3, [%l2 + LWP_STATE]
960Sstevel@tonic-gate	mov	%i3, %o3			! copy 4th arg
970Sstevel@tonic-gate	ldx	[%l2 + LWP_RU_SYSC], %g2	! pesky statistics
980Sstevel@tonic-gate	mov	%i4, %o4			! copy 5th arg
990Sstevel@tonic-gate	addx	%g2, 1, %g2
1000Sstevel@tonic-gate	stx	%g2, [%l2 + LWP_RU_SYSC]
1010Sstevel@tonic-gate	mov	%i5, %o5			! copy 6th arg
1020Sstevel@tonic-gate	! args for direct syscalls now set up
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate#ifdef TRAPTRACE
1050Sstevel@tonic-gate	!
1060Sstevel@tonic-gate	! make trap trace entry - helps in debugging
1070Sstevel@tonic-gate	!
1080Sstevel@tonic-gate	rdpr	%pstate, %l3
1090Sstevel@tonic-gate	andn	%l3, PSTATE_IE | PSTATE_AM, %g3
1100Sstevel@tonic-gate	wrpr	%g0, %g3, %pstate		! disable interrupt
1110Sstevel@tonic-gate	TRACE_PTR(%g3, %g2)			! get trace pointer
112*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g1, %g2)
1130Sstevel@tonic-gate	stxa	%g1, [%g3 + TRAP_ENT_TICK]%asi
1140Sstevel@tonic-gate	ldx	[%l1 + G1_OFF], %g1		! get syscall code
1150Sstevel@tonic-gate	TRACE_SAVE_TL_VAL(%g3, %g1)
1160Sstevel@tonic-gate	TRACE_SAVE_GL_VAL(%g3, %g0)
1170Sstevel@tonic-gate	set	TT_SC_ENTR, %g2
1180Sstevel@tonic-gate	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
1190Sstevel@tonic-gate	stxa	%g7, [%g3 + TRAP_ENT_TSTATE]%asi ! save thread in tstate space
1200Sstevel@tonic-gate	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
1210Sstevel@tonic-gate	stna	%o0, [%g3 + TRAP_ENT_F1]%asi
1220Sstevel@tonic-gate	stna	%o1, [%g3 + TRAP_ENT_F2]%asi
1230Sstevel@tonic-gate	stna	%o2, [%g3 + TRAP_ENT_F3]%asi
1240Sstevel@tonic-gate	stna	%o3, [%g3 + TRAP_ENT_F4]%asi
1250Sstevel@tonic-gate	stna	%o4, [%g3 + TRAP_ENT_TPC]%asi
1260Sstevel@tonic-gate	stna	%o5, [%g3 + TRAP_ENT_TR]%asi
1270Sstevel@tonic-gate	TRACE_NEXT(%g3, %g2, %g1)		! set new trace pointer
1280Sstevel@tonic-gate	wrpr	%g0, %l3, %pstate		! enable interrupt
1290Sstevel@tonic-gate#endif /* TRAPTRACE */
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate	!
1320Sstevel@tonic-gate	! Test for pre-system-call handling
1330Sstevel@tonic-gate	!
1340Sstevel@tonic-gate	ldub	[THREAD_REG + T_PRE_SYS], %g3	! pre-syscall proc?
1350Sstevel@tonic-gate#ifdef SYSCALLTRACE
1360Sstevel@tonic-gate	sethi	%hi(syscalltrace), %g4
1370Sstevel@tonic-gate	ld	[%g4 + %lo(syscalltrace)], %g4
1380Sstevel@tonic-gate	orcc	%g3, %g4, %g0			! pre_syscall OR syscalltrace?
1390Sstevel@tonic-gate#else
1400Sstevel@tonic-gate	tst	%g3				! is pre_syscall flag set?
1410Sstevel@tonic-gate#endif /* SYSCALLTRACE */
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate	bnz,pn	%icc, _syscall_pre
1440Sstevel@tonic-gate	nop
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate	! Fast path invocation of new_mstate
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate	mov	LMS_USER, %o0
1490Sstevel@tonic-gate	call	syscall_mstate
1500Sstevel@tonic-gate	mov	LMS_SYSTEM, %o1
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate	ldx	[%l1 + O0_OFF], %o0		! restore %o0
1530Sstevel@tonic-gate	ldx	[%l1 + O1_OFF], %o1		! restore %o1
1540Sstevel@tonic-gate	ldx	[%l1 + O2_OFF], %o2
1550Sstevel@tonic-gate	ldx     [%l1 + O3_OFF], %o3
1560Sstevel@tonic-gate	ldx     [%l1 + O4_OFF], %o4
1570Sstevel@tonic-gate	ldx	[%l1 + O5_OFF], %o5
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate	! lwp_arg now set up
1600Sstevel@tonic-gate3:
1610Sstevel@tonic-gate	!
1620Sstevel@tonic-gate	! Call the handler.  The %o's and lwp_arg have been set up.
1630Sstevel@tonic-gate	!
1640Sstevel@tonic-gate	ldx	[%l1 + G1_OFF], %g1		! get code
1650Sstevel@tonic-gate	set	sysent, %g3			! load address of vector table
1660Sstevel@tonic-gate	cmp	%g1, NSYSCALL			! check range
1670Sstevel@tonic-gate	sth	%g1, [THREAD_REG + T_SYSNUM]	! save syscall code
1680Sstevel@tonic-gate	bgeu,pn	%ncc, _syscall_ill
1690Sstevel@tonic-gate	  sll	%g1, SYSENT_SHIFT, %g4			! delay - get index
1700Sstevel@tonic-gate	add	%g3, %g4, %l4
1710Sstevel@tonic-gate	ldn	[%l4 + SY_CALLC], %g3		! load system call handler
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate	call	%g3				! call system call handler
1740Sstevel@tonic-gate	  nop
1750Sstevel@tonic-gate	!
1760Sstevel@tonic-gate	! If handler returns two ints, then we need to split the 64-bit
1770Sstevel@tonic-gate	! return value in %o0 into %o0 and %o1
1780Sstevel@tonic-gate	!
1790Sstevel@tonic-gate	lduh	[%l4 + SY_FLAGS], %l4		! load sy_flags
1800Sstevel@tonic-gate	andcc	%l4, SE_32RVAL2, %g0		! check for 2 x 32-bit
1810Sstevel@tonic-gate	bz,pt	%xcc, 5f
1820Sstevel@tonic-gate	  nop
1830Sstevel@tonic-gate	srl	%o0, 0, %o1			! lower 32-bits into %o1
1840Sstevel@tonic-gate	srlx	%o0, 32, %o0			! upper 32-bits into %o0
1850Sstevel@tonic-gate5:
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate#ifdef TRAPTRACE
1880Sstevel@tonic-gate	!
1890Sstevel@tonic-gate	! make trap trace entry for return - helps in debugging
1900Sstevel@tonic-gate	!
1910Sstevel@tonic-gate	rdpr	%pstate, %g5
1920Sstevel@tonic-gate	andn	%g5, PSTATE_IE | PSTATE_AM, %g4
1930Sstevel@tonic-gate	wrpr	%g0, %g4, %pstate		! disable interrupt
1940Sstevel@tonic-gate	TRACE_PTR(%g4, %g2)			! get trace pointer
195*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g2, %g3)
1960Sstevel@tonic-gate	stxa	%g2, [%g4 + TRAP_ENT_TICK]%asi
1970Sstevel@tonic-gate	lduh	[THREAD_REG + T_SYSNUM], %g2
1980Sstevel@tonic-gate	TRACE_SAVE_TL_VAL(%g4, %g2)
1990Sstevel@tonic-gate	TRACE_SAVE_GL_VAL(%g4, %g0)
2000Sstevel@tonic-gate	mov	TT_SC_RET, %g2			! system call return code
2010Sstevel@tonic-gate	stha	%g2, [%g4 + TRAP_ENT_TT]%asi
2020Sstevel@tonic-gate	ldn	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
2030Sstevel@tonic-gate	stna	%g2, [%g4 + TRAP_ENT_TPC]%asi
2040Sstevel@tonic-gate	ldx	[%l1 + TSTATE_OFF], %g2		! get saved tstate
2050Sstevel@tonic-gate	stxa	%g2, [%g4 + TRAP_ENT_TSTATE]%asi
2060Sstevel@tonic-gate	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
2070Sstevel@tonic-gate	stna	THREAD_REG, [%g4 + TRAP_ENT_TR]%asi
2080Sstevel@tonic-gate	stna	%o0, [%g4 + TRAP_ENT_F1]%asi
2090Sstevel@tonic-gate	stna	%o1, [%g4 + TRAP_ENT_F2]%asi
2100Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
2110Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
2120Sstevel@tonic-gate	TRACE_NEXT(%g4, %g2, %g3)		! set new trace pointer
2130Sstevel@tonic-gate	wrpr	%g0, %g5, %pstate		! enable interrupt
2140Sstevel@tonic-gate#endif /* TRAPTRACE */
2150Sstevel@tonic-gate	!
2160Sstevel@tonic-gate	! Check for post-syscall processing.
2170Sstevel@tonic-gate	! This tests all members of the union containing t_astflag, t_post_sys,
2180Sstevel@tonic-gate	! and t_sig_check with one test.
2190Sstevel@tonic-gate	!
2200Sstevel@tonic-gate	ld	[THREAD_REG + T_POST_SYS_AST], %g1
2210Sstevel@tonic-gate#ifdef SYSCALLTRACE
2220Sstevel@tonic-gate	sethi	%hi(syscalltrace), %g4
2230Sstevel@tonic-gate	ld	[%g4 + %lo(syscalltrace)], %g4
2240Sstevel@tonic-gate	orcc	%g4, %g1, %g0			! OR in syscalltrace
2250Sstevel@tonic-gate#else
2260Sstevel@tonic-gate	tst	%g1				! need post-processing?
2270Sstevel@tonic-gate#endif /* SYSCALLTRACE */
2280Sstevel@tonic-gate	bnz,pn	%icc, _syscall_post		! yes - post_syscall or AST set
2290Sstevel@tonic-gate	mov	LWP_USER, %g1
2300Sstevel@tonic-gate	stb	%g1, [%l2 + LWP_STATE]		! set lwp_state
2310Sstevel@tonic-gate	stx	%o0, [%l1 + O0_OFF]		! set rp->r_o0
2320Sstevel@tonic-gate	stx	%o1, [%l1 + O1_OFF]		! set rp->r_o1
2330Sstevel@tonic-gate	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
2340Sstevel@tonic-gate	ldx	[%l1 + TSTATE_OFF], %g1		! get saved tstate
2350Sstevel@tonic-gate	ldn	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
2360Sstevel@tonic-gate	mov	CCR_IC, %g3
2370Sstevel@tonic-gate	sllx	%g3, TSTATE_CCR_SHIFT, %g3
2380Sstevel@tonic-gate	add	%g2, 4, %g4			! calc new npc
2390Sstevel@tonic-gate	andn	%g1, %g3, %g1			! clear carry bit for no error
2400Sstevel@tonic-gate	stn	%g2, [%l1 + PC_OFF]
2410Sstevel@tonic-gate	stn	%g4, [%l1 + nPC_OFF]
2420Sstevel@tonic-gate	stx	%g1, [%l1 + TSTATE_OFF]
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate	! Switch mstate back on the way out
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate	mov	LMS_SYSTEM, %o0
2470Sstevel@tonic-gate	call	syscall_mstate
2480Sstevel@tonic-gate	mov	LMS_USER, %o1
2490Sstevel@tonic-gate	jmp	%l0 + 8
2500Sstevel@tonic-gate	 nop
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate_syscall_pre:
2530Sstevel@tonic-gate	ldx	[%l1 + G1_OFF], %g1
2540Sstevel@tonic-gate	call	pre_syscall			! abort = pre_syscall(arg0)
2550Sstevel@tonic-gate	sth	%g1, [THREAD_REG + T_SYSNUM]
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate	brnz,pn	%o0, _syscall_post		! did it abort?
2580Sstevel@tonic-gate	nop
2590Sstevel@tonic-gate	ldx	[%l1 + O0_OFF], %o0		! reload args
2600Sstevel@tonic-gate	ldx	[%l1 + O1_OFF], %o1
2610Sstevel@tonic-gate	ldx	[%l1 + O2_OFF], %o2
2620Sstevel@tonic-gate	ldx	[%l1 + O3_OFF], %o3
2630Sstevel@tonic-gate	ldx	[%l1 + O4_OFF], %o4
2640Sstevel@tonic-gate	ba,pt	%xcc, 3b
2650Sstevel@tonic-gate	ldx	[%l1 + O5_OFF], %o5
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate	!
2680Sstevel@tonic-gate	! Floating-point trap was pending at start of system call.
2690Sstevel@tonic-gate	! Here with:
2700Sstevel@tonic-gate	!	%l3 = mpcb_flags
2710Sstevel@tonic-gate	!
2720Sstevel@tonic-gate_syscall_fp:
2730Sstevel@tonic-gate	andn	%l3, FP_TRAPPED, %l3
2740Sstevel@tonic-gate	st	%l3, [%sp + STACK_BIAS + MPCB_FLAGS] 	! clear FP_TRAPPED
2750Sstevel@tonic-gate	jmp	%l0 + 8				! return to user_rtt
2760Sstevel@tonic-gate	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate	!
2790Sstevel@tonic-gate	! illegal system call - syscall number out of range
2800Sstevel@tonic-gate	!
2810Sstevel@tonic-gate_syscall_ill:
2820Sstevel@tonic-gate	call	nosys
2830Sstevel@tonic-gate	nop
2840Sstevel@tonic-gate	!
2850Sstevel@tonic-gate	! Post-syscall with special processing needed.
2860Sstevel@tonic-gate	!
2870Sstevel@tonic-gate_syscall_post:
2880Sstevel@tonic-gate	call	post_syscall			! post_syscall(rvals)
2890Sstevel@tonic-gate	nop
2900Sstevel@tonic-gate	jmp	%l0 + 8				! return to user_rtt
2910Sstevel@tonic-gate	nop
2920Sstevel@tonic-gate	SET_SIZE(syscall_trap)
2930Sstevel@tonic-gate#endif	/* lint */
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate#if defined(lint) || defined(__lint)
2960Sstevel@tonic-gate
2970Sstevel@tonic-gatevoid
2980Sstevel@tonic-gatesyscall_trap32(void)	/* for tags only - trap handler - not called from C */
2990Sstevel@tonic-gate{}
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate#else /* lint */
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate/*
3040Sstevel@tonic-gate * System call trap handler for ILP32 processes.
3050Sstevel@tonic-gate *
3060Sstevel@tonic-gate * We branch here from sys_trap when a system call occurs.
3070Sstevel@tonic-gate *
3080Sstevel@tonic-gate * Entry:
3090Sstevel@tonic-gate *	%o0 = regs
3100Sstevel@tonic-gate *
3110Sstevel@tonic-gate * Usage:
3120Sstevel@tonic-gate *	%l0 = saved return address
3130Sstevel@tonic-gate *	%l1 = saved regs
3140Sstevel@tonic-gate *	%l2 = lwp
3150Sstevel@tonic-gate */
3160Sstevel@tonic-gate	ENTRY_NP(syscall_trap32)
3170Sstevel@tonic-gate	ldx	[THREAD_REG + T_CPU], %g1	! get cpu pointer
3180Sstevel@tonic-gate	mov	%o7, %l0			! save return addr
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate	!
3210Sstevel@tonic-gate	! If the trapping thread has the address mask bit clear, then it's
3220Sstevel@tonic-gate	!   a 64-bit process, and has no business calling 32-bit syscalls.
3230Sstevel@tonic-gate	!
3240Sstevel@tonic-gate	ldx	[%o0 + TSTATE_OFF], %l1		! saved %tstate.am is that
3250Sstevel@tonic-gate	andcc	%l1, TSTATE_AM, %l1		!   of the trapping proc
3260Sstevel@tonic-gate	be,pn	%xcc, _syscall_ill32		!
3270Sstevel@tonic-gate	  mov	%o0, %l1			! save reg pointer
3280Sstevel@tonic-gate	srl	%i0, 0, %o0			! copy 1st arg, clear high bits
3290Sstevel@tonic-gate	srl	%i1, 0, %o1			! copy 2nd arg, clear high bits
3300Sstevel@tonic-gate	ldx	[%g1 + CPU_STATS_SYS_SYSCALL], %g2
3310Sstevel@tonic-gate	inc	%g2				! cpu_stats.sys.syscall++
3320Sstevel@tonic-gate	stx	%g2, [%g1 + CPU_STATS_SYS_SYSCALL]
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate	!
3350Sstevel@tonic-gate	! Set new state for LWP
3360Sstevel@tonic-gate	!
3370Sstevel@tonic-gate	ldx	[THREAD_REG + T_LWP], %l2
3380Sstevel@tonic-gate	mov	LWP_SYS, %g3
3390Sstevel@tonic-gate	srl	%i2, 0, %o2			! copy 3rd arg, clear high bits
3400Sstevel@tonic-gate	stb	%g3, [%l2 + LWP_STATE]
3410Sstevel@tonic-gate	srl	%i3, 0, %o3			! copy 4th arg, clear high bits
3420Sstevel@tonic-gate	ldx	[%l2 + LWP_RU_SYSC], %g2	! pesky statistics
3430Sstevel@tonic-gate	srl	%i4, 0, %o4			! copy 5th arg, clear high bits
3440Sstevel@tonic-gate	addx	%g2, 1, %g2
3450Sstevel@tonic-gate	stx	%g2, [%l2 + LWP_RU_SYSC]
3460Sstevel@tonic-gate	srl	%i5, 0, %o5			! copy 6th arg, clear high bits
3470Sstevel@tonic-gate	! args for direct syscalls now set up
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate#ifdef TRAPTRACE
3500Sstevel@tonic-gate	!
3510Sstevel@tonic-gate	! make trap trace entry - helps in debugging
3520Sstevel@tonic-gate	!
3530Sstevel@tonic-gate	rdpr	%pstate, %l3
3540Sstevel@tonic-gate	andn	%l3, PSTATE_IE | PSTATE_AM, %g3
3550Sstevel@tonic-gate	wrpr	%g0, %g3, %pstate		! disable interrupt
3560Sstevel@tonic-gate	TRACE_PTR(%g3, %g2)			! get trace pointer
357*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g1, %g2)
3580Sstevel@tonic-gate	stxa	%g1, [%g3 + TRAP_ENT_TICK]%asi
3590Sstevel@tonic-gate	ldx	[%l1 + G1_OFF], %g1		! get syscall code
3600Sstevel@tonic-gate	TRACE_SAVE_TL_VAL(%g3, %g1)
3610Sstevel@tonic-gate	TRACE_SAVE_GL_VAL(%g3, %g0)
3620Sstevel@tonic-gate	set	TT_SC_ENTR, %g2
3630Sstevel@tonic-gate	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
3640Sstevel@tonic-gate	stxa	%g7, [%g3 + TRAP_ENT_TSTATE]%asi ! save thread in tstate space
3650Sstevel@tonic-gate	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
3660Sstevel@tonic-gate	stna	%o0, [%g3 + TRAP_ENT_F1]%asi
3670Sstevel@tonic-gate	stna	%o1, [%g3 + TRAP_ENT_F2]%asi
3680Sstevel@tonic-gate	stna	%o2, [%g3 + TRAP_ENT_F3]%asi
3690Sstevel@tonic-gate	stna	%o3, [%g3 + TRAP_ENT_F4]%asi
3700Sstevel@tonic-gate	stna	%o4, [%g3 + TRAP_ENT_TPC]%asi
3710Sstevel@tonic-gate	stna	%o5, [%g3 + TRAP_ENT_TR]%asi
3720Sstevel@tonic-gate	TRACE_NEXT(%g3, %g2, %g1)		! set new trace pointer
3730Sstevel@tonic-gate	wrpr	%g0, %l3, %pstate		! enable interrupt
3740Sstevel@tonic-gate#endif /* TRAPTRACE */
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate	!
3770Sstevel@tonic-gate	! Test for pre-system-call handling
3780Sstevel@tonic-gate	!
3790Sstevel@tonic-gate	ldub	[THREAD_REG + T_PRE_SYS], %g3	! pre-syscall proc?
3800Sstevel@tonic-gate#ifdef SYSCALLTRACE
3810Sstevel@tonic-gate	sethi	%hi(syscalltrace), %g4
3820Sstevel@tonic-gate	ld	[%g4 + %lo(syscalltrace)], %g4
3830Sstevel@tonic-gate	orcc	%g3, %g4, %g0			! pre_syscall OR syscalltrace?
3840Sstevel@tonic-gate#else
3850Sstevel@tonic-gate	tst	%g3				! is pre_syscall flag set?
3860Sstevel@tonic-gate#endif /* SYSCALLTRACE */
3870Sstevel@tonic-gate	bnz,pn	%icc, _syscall_pre32		! yes - pre_syscall needed
3880Sstevel@tonic-gate	  nop
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate	! Fast path invocation of new_mstate
3910Sstevel@tonic-gate	mov	LMS_USER, %o0
3920Sstevel@tonic-gate	call 	syscall_mstate
3930Sstevel@tonic-gate	mov	LMS_SYSTEM, %o1
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate 	lduw	[%l1 + O0_OFF + 4], %o0		! reload 32-bit args
3960Sstevel@tonic-gate	lduw	[%l1 + O1_OFF + 4], %o1
3970Sstevel@tonic-gate	lduw	[%l1 + O2_OFF + 4], %o2
3980Sstevel@tonic-gate	lduw	[%l1 + O3_OFF + 4], %o3
3990Sstevel@tonic-gate	lduw	[%l1 + O4_OFF + 4], %o4
4000Sstevel@tonic-gate	lduw	[%l1 + O5_OFF + 4], %o5
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate	! lwp_arg now set up
4030Sstevel@tonic-gate3:
4040Sstevel@tonic-gate	!
4050Sstevel@tonic-gate	! Call the handler.  The %o's have been set up.
4060Sstevel@tonic-gate	!
4070Sstevel@tonic-gate	lduw	[%l1 + G1_OFF + 4], %g1		! get 32-bit code
4080Sstevel@tonic-gate	set	sysent32, %g3			! load address of vector table
4090Sstevel@tonic-gate	cmp	%g1, NSYSCALL			! check range
4100Sstevel@tonic-gate	sth	%g1, [THREAD_REG + T_SYSNUM]	! save syscall code
4110Sstevel@tonic-gate	bgeu,pn	%ncc, _syscall_ill32
4120Sstevel@tonic-gate	  sll	%g1, SYSENT_SHIFT, %g4		! delay - get index
4130Sstevel@tonic-gate	add	%g3, %g4, %g5			! g5 = addr of sysentry
4140Sstevel@tonic-gate	ldx	[%g5 + SY_CALLC], %g3		! load system call handler
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate	brnz,a,pt %g1, 4f			! check for indir()
4170Sstevel@tonic-gate	mov	%g5, %l4			! save addr of sysentry
4180Sstevel@tonic-gate	!
4190Sstevel@tonic-gate	! Yuck.  If %g1 is zero, that means we're doing a syscall() via the
4200Sstevel@tonic-gate	! indirect system call.  That means we have to check the
4210Sstevel@tonic-gate	! flags of the targetted system call, not the indirect system call
4220Sstevel@tonic-gate	! itself.  See return value handling code below.
4230Sstevel@tonic-gate	!
4240Sstevel@tonic-gate	set	sysent32, %l4			! load address of vector table
4250Sstevel@tonic-gate	cmp	%o0, NSYSCALL			! check range
4260Sstevel@tonic-gate	bgeu,pn	%ncc, 4f			! out of range, let C handle it
4270Sstevel@tonic-gate	  sll	%o0, SYSENT_SHIFT, %g4		! delay - get index
4280Sstevel@tonic-gate	add	%g4, %l4, %l4			! compute & save addr of sysent
4290Sstevel@tonic-gate4:
4300Sstevel@tonic-gate	call	%g3				! call system call handler
4310Sstevel@tonic-gate	nop
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate	!
4340Sstevel@tonic-gate	! If handler returns long long then we need to split the 64 bit
4350Sstevel@tonic-gate	! return value in %o0 into %o0 and %o1 for ILP32 clients.
4360Sstevel@tonic-gate	!
4370Sstevel@tonic-gate	lduh    [%l4 + SY_FLAGS], %g4           ! load sy_flags
4380Sstevel@tonic-gate	andcc	%g4, SE_64RVAL | SE_32RVAL2, %g0 ! check for 64-bit return
4390Sstevel@tonic-gate	bz,a,pt	%xcc, 5f
4400Sstevel@tonic-gate	  srl	%o0, 0, %o0			! 32-bit only
4410Sstevel@tonic-gate	srl	%o0, 0, %o1			! lower 32 bits into %o1
4420Sstevel@tonic-gate	srlx	%o0, 32, %o0			! upper 32 bits into %o0
4430Sstevel@tonic-gate5:
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate#ifdef TRAPTRACE
4460Sstevel@tonic-gate	!
4470Sstevel@tonic-gate	! make trap trace entry for return - helps in debugging
4480Sstevel@tonic-gate	!
4490Sstevel@tonic-gate	rdpr	%pstate, %g5
4500Sstevel@tonic-gate	andn	%g5, PSTATE_IE | PSTATE_AM, %g4
4510Sstevel@tonic-gate	wrpr	%g0, %g4, %pstate		! disable interrupt
4520Sstevel@tonic-gate	TRACE_PTR(%g4, %g2)			! get trace pointer
453*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g2, %g3)
4540Sstevel@tonic-gate	stxa	%g2, [%g4 + TRAP_ENT_TICK]%asi
4550Sstevel@tonic-gate	lduh	[THREAD_REG + T_SYSNUM], %g2
4560Sstevel@tonic-gate	TRACE_SAVE_TL_VAL(%g4, %g2)
4570Sstevel@tonic-gate	TRACE_SAVE_GL_VAL(%g4, %g0)
4580Sstevel@tonic-gate	mov	TT_SC_RET, %g2			! system call return code
4590Sstevel@tonic-gate	stha	%g2, [%g4 + TRAP_ENT_TT]%asi
4600Sstevel@tonic-gate	ldx	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
4610Sstevel@tonic-gate	stna	%g2, [%g4 + TRAP_ENT_TPC]%asi
4620Sstevel@tonic-gate	ldx	[%l1 + TSTATE_OFF], %g2		! get saved tstate
4630Sstevel@tonic-gate	stxa	%g2, [%g4 + TRAP_ENT_TSTATE]%asi
4640Sstevel@tonic-gate	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
4650Sstevel@tonic-gate	stna	THREAD_REG, [%g4 + TRAP_ENT_TR]%asi
4660Sstevel@tonic-gate	stna	%o0, [%g4 + TRAP_ENT_F1]%asi
4670Sstevel@tonic-gate	stna	%o1, [%g4 + TRAP_ENT_F2]%asi
4680Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
4690Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
4700Sstevel@tonic-gate	TRACE_NEXT(%g4, %g2, %g3)		! set new trace pointer
4710Sstevel@tonic-gate	wrpr	%g0, %g5, %pstate		! enable interrupt
4720Sstevel@tonic-gate#endif /* TRAPTRACE */
4730Sstevel@tonic-gate	!
4740Sstevel@tonic-gate	! Check for post-syscall processing.
4750Sstevel@tonic-gate	! This tests all members of the union containing t_astflag, t_post_sys,
4760Sstevel@tonic-gate	! and t_sig_check with one test.
4770Sstevel@tonic-gate	!
4780Sstevel@tonic-gate	ld	[THREAD_REG + T_POST_SYS_AST], %g1
4790Sstevel@tonic-gate#ifdef SYSCALLTRACE
4800Sstevel@tonic-gate	sethi	%hi(syscalltrace), %g4
4810Sstevel@tonic-gate	ld	[%g4 + %lo(syscalltrace)], %g4
4820Sstevel@tonic-gate	orcc	%g4, %g1, %g0			! OR in syscalltrace
4830Sstevel@tonic-gate#else
4840Sstevel@tonic-gate	tst	%g1				! need post-processing?
4850Sstevel@tonic-gate#endif /* SYSCALLTRACE */
4860Sstevel@tonic-gate	bnz,pn	%icc, _syscall_post32		! yes - post_syscall or AST set
4870Sstevel@tonic-gate	mov	LWP_USER, %g1
4880Sstevel@tonic-gate	stb	%g1, [%l2 + LWP_STATE]		! set lwp_state
4890Sstevel@tonic-gate	stx	%o0, [%l1 + O0_OFF]		! set rp->r_o0
4900Sstevel@tonic-gate	stx	%o1, [%l1 + O1_OFF]		! set rp->r_o1
4910Sstevel@tonic-gate	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
4920Sstevel@tonic-gate	ldx	[%l1 + TSTATE_OFF], %g1		! get saved tstate
4930Sstevel@tonic-gate	ldx	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
4940Sstevel@tonic-gate	mov	CCR_IC, %g3
4950Sstevel@tonic-gate	sllx	%g3, TSTATE_CCR_SHIFT, %g3
4960Sstevel@tonic-gate	add	%g2, 4, %g4			! calc new npc
4970Sstevel@tonic-gate	andn	%g1, %g3, %g1			! clear carry bit for no error
4980Sstevel@tonic-gate	stx	%g2, [%l1 + PC_OFF]
4990Sstevel@tonic-gate	stx	%g4, [%l1 + nPC_OFF]
5000Sstevel@tonic-gate	stx	%g1, [%l1 + TSTATE_OFF]
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate	! fast path outbound microstate accounting call
5030Sstevel@tonic-gate	mov	LMS_SYSTEM, %o0
5040Sstevel@tonic-gate	call 	syscall_mstate
5050Sstevel@tonic-gate	mov	LMS_USER, %o1
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate	jmp	%l0 + 8
5080Sstevel@tonic-gate	 nop
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate_syscall_pre32:
5120Sstevel@tonic-gate	ldx	[%l1 + G1_OFF], %g1
5130Sstevel@tonic-gate	call	pre_syscall			! abort = pre_syscall(arg0)
5140Sstevel@tonic-gate	sth	%g1, [THREAD_REG + T_SYSNUM]
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate	brnz,pn	%o0, _syscall_post32		! did it abort?
5170Sstevel@tonic-gate	nop
5180Sstevel@tonic-gate 	lduw	[%l1 + O0_OFF + 4], %o0		! reload 32-bit args
5190Sstevel@tonic-gate	lduw	[%l1 + O1_OFF + 4], %o1
5200Sstevel@tonic-gate	lduw	[%l1 + O2_OFF + 4], %o2
5210Sstevel@tonic-gate	lduw	[%l1 + O3_OFF + 4], %o3
5220Sstevel@tonic-gate	lduw	[%l1 + O4_OFF + 4], %o4
5230Sstevel@tonic-gate	ba,pt	%xcc, 3b
5240Sstevel@tonic-gate	lduw	[%l1 + O5_OFF + 4], %o5
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate	!
5270Sstevel@tonic-gate	! Floating-point trap was pending at start of system call.
5280Sstevel@tonic-gate	! Here with:
5290Sstevel@tonic-gate	!	%l3 = mpcb_flags
5300Sstevel@tonic-gate	!
5310Sstevel@tonic-gate_syscall_fp32:
5320Sstevel@tonic-gate	andn	%l3, FP_TRAPPED, %l3
5330Sstevel@tonic-gate	st	%l3, [%sp + STACK_BIAS + MPCB_FLAGS] 	! clear FP_TRAPPED
5340Sstevel@tonic-gate	jmp	%l0 + 8				! return to user_rtt
5350Sstevel@tonic-gate	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate	!
5380Sstevel@tonic-gate	! illegal system call - syscall number out of range
5390Sstevel@tonic-gate	!
5400Sstevel@tonic-gate_syscall_ill32:
5410Sstevel@tonic-gate	call	nosys
5420Sstevel@tonic-gate	nop
5430Sstevel@tonic-gate	!
5440Sstevel@tonic-gate	! Post-syscall with special processing needed.
5450Sstevel@tonic-gate	!
5460Sstevel@tonic-gate_syscall_post32:
5470Sstevel@tonic-gate	call	post_syscall			! post_syscall(rvals)
5480Sstevel@tonic-gate	nop
5490Sstevel@tonic-gate	jmp	%l0 + 8				! return to user_rtt
5500Sstevel@tonic-gate	nop
5510Sstevel@tonic-gate	SET_SIZE(syscall_trap32)
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate#endif /* lint */
5540Sstevel@tonic-gate
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate/*
5570Sstevel@tonic-gate * lwp_rtt - start execution in newly created LWP.
5580Sstevel@tonic-gate *	Here with t_post_sys set by lwp_create, and lwp_eosys == JUSTRETURN,
5590Sstevel@tonic-gate *	so that post_syscall() will run and the registers will
5600Sstevel@tonic-gate *	simply be restored.
5610Sstevel@tonic-gate *	This must go out through sys_rtt instead of syscall_rtt.
5620Sstevel@tonic-gate */
5630Sstevel@tonic-gate#if defined(lint) || defined(__lint)
5640Sstevel@tonic-gate
5650Sstevel@tonic-gatevoid
5660Sstevel@tonic-gatelwp_rtt_initial(void)
5670Sstevel@tonic-gate{}
5680Sstevel@tonic-gate
5690Sstevel@tonic-gatevoid
5700Sstevel@tonic-gatelwp_rtt(void)
5710Sstevel@tonic-gate{}
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate#else	/* lint */
5740Sstevel@tonic-gate	ENTRY_NP(lwp_rtt_initial)
5750Sstevel@tonic-gate	ldn	[THREAD_REG + T_STACK], %l7
5760Sstevel@tonic-gate	call	__dtrace_probe___proc_start
5770Sstevel@tonic-gate	sub	%l7, STACK_BIAS, %sp
578769Sraf	ba,a,pt	%xcc, 0f
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate	ENTRY_NP(lwp_rtt)
5810Sstevel@tonic-gate	ldn	[THREAD_REG + T_STACK], %l7
5820Sstevel@tonic-gate	sub	%l7, STACK_BIAS, %sp
5830Sstevel@tonic-gate0:
5840Sstevel@tonic-gate	call	__dtrace_probe___proc_lwp__start
5850Sstevel@tonic-gate	nop
5860Sstevel@tonic-gate	call	dtrace_systrace_rtt
5870Sstevel@tonic-gate	add	%sp, REGOFF + STACK_BIAS, %l7
5880Sstevel@tonic-gate	ldx	[%l7 + O0_OFF], %o0
5890Sstevel@tonic-gate	call	post_syscall
5900Sstevel@tonic-gate	ldx	[%l7 + O1_OFF], %o1
5910Sstevel@tonic-gate	ba,a,pt	%xcc, user_rtt
5920Sstevel@tonic-gate	SET_SIZE(lwp_rtt)
593769Sraf	SET_SIZE(lwp_rtt_initial)
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate#endif	/* lint */
596