Home | History | Annotate | Download | only in ml
      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, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 /*
     30  * System call trap handler.
     31  */
     32 #include <sys/asm_linkage.h>
     33 #include <sys/machpcb.h>
     34 #include <sys/machthread.h>
     35 #include <sys/syscall.h>
     36 #include <sys/trap.h>
     37 #include <sys/machtrap.h>
     38 #include <sys/pcb.h>
     39 #include <sys/machparam.h>
     40 
     41 #if !defined(lint) && !defined(__lint)
     42 #include "assym.h"
     43 #endif
     44 
     45 #ifdef TRAPTRACE
     46 #include <sys/traptrace.h>
     47 #endif /* TRAPTRACE */
     48 
     49 #if defined(lint) || defined(__lint)
     50 
     51 /*ARGSUSED*/
     52 void
     53 syscall_trap(struct regs *rp)	/* for tags only; not called from C */
     54 {}
     55 
     56 #else /* lint */
     57 
     58 #if (1 << SYSENT_SHIFT) != SYSENT_SIZE
     59 #error	"SYSENT_SHIFT does not correspond to size of sysent structure"
     60 #endif
     61 
     62 /*
     63  * Native System call trap handler.
     64  *
     65  * We branch here from sys_trap when a 64-bit system call occurs.
     66  *
     67  * Entry:
     68  *	%o0 = regs
     69  *
     70  * Usage:
     71  *	%l0 = saved return address
     72  *	%l1 = saved regs
     73  *	%l2 = lwp
     74  */
     75 	ENTRY_NP(syscall_trap)
     76 	ldn	[THREAD_REG + T_CPU], %g1	! get cpu pointer
     77 	mov	%o7, %l0			! save return addr
     78 	!
     79 	! If the trapping thread has the address mask bit set, then it's
     80 	!   a 32-bit process, and has no business calling 64-bit syscalls.
     81 	!
     82 	ldx	[%o0 + TSTATE_OFF], %l1		! saved %tstate.am is that
     83 	andcc	%l1, TSTATE_AM, %l1		!   of the trapping proc
     84 	bne,pn	%xcc, _syscall_ill		!
     85 	mov	%o0, %l1			! save reg pointer
     86 	mov	%i0, %o0			! copy 1st arg
     87 	mov	%i1, %o1			! copy 2nd arg
     88 	ldx	[%g1 + CPU_STATS_SYS_SYSCALL], %g2
     89 	inc	%g2				! cpu_stats.sys.syscall++
     90 	stx	%g2, [%g1 + CPU_STATS_SYS_SYSCALL]
     91 
     92 	!
     93 	! Set new state for LWP
     94 	!
     95 	ldn	[THREAD_REG + T_LWP], %l2
     96 	mov	LWP_SYS, %g3
     97 	mov	%i2, %o2			! copy 3rd arg
     98 	stb	%g3, [%l2 + LWP_STATE]
     99 	mov	%i3, %o3			! copy 4th arg
    100 	ldx	[%l2 + LWP_RU_SYSC], %g2	! pesky statistics
    101 	mov	%i4, %o4			! copy 5th arg
    102 	addx	%g2, 1, %g2
    103 	stx	%g2, [%l2 + LWP_RU_SYSC]
    104 	mov	%i5, %o5			! copy 6th arg
    105 	! args for direct syscalls now set up
    106 
    107 #ifdef TRAPTRACE
    108 	!
    109 	! make trap trace entry - helps in debugging
    110 	!
    111 	rdpr	%pstate, %l3
    112 	andn	%l3, PSTATE_IE | PSTATE_AM, %g3
    113 	wrpr	%g0, %g3, %pstate		! disable interrupt
    114 	TRACE_PTR(%g3, %g2)			! get trace pointer
    115 	GET_TRACE_TICK(%g1)
    116 	stxa	%g1, [%g3 + TRAP_ENT_TICK]%asi
    117 	ldx	[%l1 + G1_OFF], %g1		! get syscall code
    118 	TRACE_SAVE_TL_VAL(%g3, %g1)
    119 	TRACE_SAVE_GL_VAL(%g3, %g0)
    120 	set	TT_SC_ENTR, %g2
    121 	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
    122 	stxa	%g7, [%g3 + TRAP_ENT_TSTATE]%asi ! save thread in tstate space
    123 	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
    124 	stna	%o0, [%g3 + TRAP_ENT_F1]%asi
    125 	stna	%o1, [%g3 + TRAP_ENT_F2]%asi
    126 	stna	%o2, [%g3 + TRAP_ENT_F3]%asi
    127 	stna	%o3, [%g3 + TRAP_ENT_F4]%asi
    128 	stna	%o4, [%g3 + TRAP_ENT_TPC]%asi
    129 	stna	%o5, [%g3 + TRAP_ENT_TR]%asi
    130 	TRACE_NEXT(%g3, %g2, %g1)		! set new trace pointer
    131 	wrpr	%g0, %l3, %pstate		! enable interrupt
    132 #endif /* TRAPTRACE */
    133 
    134 	!
    135 	! Test for pre-system-call handling
    136 	!
    137 	ldub	[THREAD_REG + T_PRE_SYS], %g3	! pre-syscall proc?
    138 #ifdef SYSCALLTRACE
    139 	sethi	%hi(syscalltrace), %g4
    140 	ld	[%g4 + %lo(syscalltrace)], %g4
    141 	orcc	%g3, %g4, %g0			! pre_syscall OR syscalltrace?
    142 #else
    143 	tst	%g3				! is pre_syscall flag set?
    144 #endif /* SYSCALLTRACE */
    145 
    146 	bnz,pn	%icc, _syscall_pre
    147 	nop
    148 
    149 	! Fast path invocation of new_mstate
    150 
    151 	mov	LMS_USER, %o0
    152 	call	syscall_mstate
    153 	mov	LMS_SYSTEM, %o1
    154 
    155 	ldx	[%l1 + O0_OFF], %o0		! restore %o0
    156 	ldx	[%l1 + O1_OFF], %o1		! restore %o1
    157 	ldx	[%l1 + O2_OFF], %o2
    158 	ldx     [%l1 + O3_OFF], %o3
    159 	ldx     [%l1 + O4_OFF], %o4
    160 	ldx	[%l1 + O5_OFF], %o5
    161 
    162 	! lwp_arg now set up
    163 3:
    164 	!
    165 	! Call the handler.  The %o's and lwp_arg have been set up.
    166 	!
    167 	ldx	[%l1 + G1_OFF], %g1		! get code
    168 	set	sysent, %g3			! load address of vector table
    169 	cmp	%g1, NSYSCALL			! check range
    170 	sth	%g1, [THREAD_REG + T_SYSNUM]	! save syscall code
    171 	bgeu,pn	%ncc, _syscall_ill
    172 	  sll	%g1, SYSENT_SHIFT, %g4			! delay - get index
    173 	add	%g3, %g4, %l4
    174 	ldn	[%l4 + SY_CALLC], %g3		! load system call handler
    175 
    176 	call	%g3				! call system call handler
    177 	  nop
    178 	!
    179 	! If handler returns two ints, then we need to split the 64-bit
    180 	! return value in %o0 into %o0 and %o1
    181 	!
    182 	lduh	[%l4 + SY_FLAGS], %l4		! load sy_flags
    183 	andcc	%l4, SE_32RVAL2, %g0		! check for 2 x 32-bit
    184 	bz,pt	%xcc, 5f
    185 	  nop
    186 	srl	%o0, 0, %o1			! lower 32-bits into %o1
    187 	srlx	%o0, 32, %o0			! upper 32-bits into %o0
    188 5:
    189 
    190 #ifdef TRAPTRACE
    191 	!
    192 	! make trap trace entry for return - helps in debugging
    193 	!
    194 	rdpr	%pstate, %g5
    195 	andn	%g5, PSTATE_IE | PSTATE_AM, %g4
    196 	wrpr	%g0, %g4, %pstate		! disable interrupt
    197 	TRACE_PTR(%g4, %g2)			! get trace pointer
    198 	GET_TRACE_TICK(%g2)
    199 	stxa	%g2, [%g4 + TRAP_ENT_TICK]%asi
    200 	lduh	[THREAD_REG + T_SYSNUM], %g2
    201 	TRACE_SAVE_TL_VAL(%g4, %g2)
    202 	TRACE_SAVE_GL_VAL(%g4, %g0)
    203 	mov	TT_SC_RET, %g2			! system call return code
    204 	stha	%g2, [%g4 + TRAP_ENT_TT]%asi
    205 	ldn	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
    206 	stna	%g2, [%g4 + TRAP_ENT_TPC]%asi
    207 	ldx	[%l1 + TSTATE_OFF], %g2		! get saved tstate
    208 	stxa	%g2, [%g4 + TRAP_ENT_TSTATE]%asi
    209 	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
    210 	stna	THREAD_REG, [%g4 + TRAP_ENT_TR]%asi
    211 	stna	%o0, [%g4 + TRAP_ENT_F1]%asi
    212 	stna	%o1, [%g4 + TRAP_ENT_F2]%asi
    213 	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
    214 	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
    215 	TRACE_NEXT(%g4, %g2, %g3)		! set new trace pointer
    216 	wrpr	%g0, %g5, %pstate		! enable interrupt
    217 #endif /* TRAPTRACE */
    218 	!
    219 	! Check for post-syscall processing.
    220 	! This tests all members of the union containing t_astflag, t_post_sys,
    221 	! and t_sig_check with one test.
    222 	!
    223 	ld	[THREAD_REG + T_POST_SYS_AST], %g1
    224 #ifdef SYSCALLTRACE
    225 	sethi	%hi(syscalltrace), %g4
    226 	ld	[%g4 + %lo(syscalltrace)], %g4
    227 	orcc	%g4, %g1, %g0			! OR in syscalltrace
    228 #else
    229 	tst	%g1				! need post-processing?
    230 #endif /* SYSCALLTRACE */
    231 	bnz,pn	%icc, _syscall_post		! yes - post_syscall or AST set
    232 	mov	LWP_USER, %g1
    233 	stb	%g1, [%l2 + LWP_STATE]		! set lwp_state
    234 	stx	%o0, [%l1 + O0_OFF]		! set rp->r_o0
    235 	stx	%o1, [%l1 + O1_OFF]		! set rp->r_o1
    236 	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
    237 	ldx	[%l1 + TSTATE_OFF], %g1		! get saved tstate
    238 	ldn	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
    239 	mov	CCR_IC, %g3
    240 	sllx	%g3, TSTATE_CCR_SHIFT, %g3
    241 	add	%g2, 4, %g4			! calc new npc
    242 	andn	%g1, %g3, %g1			! clear carry bit for no error
    243 	stn	%g2, [%l1 + PC_OFF]
    244 	stn	%g4, [%l1 + nPC_OFF]
    245 	stx	%g1, [%l1 + TSTATE_OFF]
    246 
    247 	! Switch mstate back on the way out
    248 
    249 	mov	LMS_SYSTEM, %o0
    250 	call	syscall_mstate
    251 	mov	LMS_USER, %o1
    252 	jmp	%l0 + 8
    253 	 nop
    254 
    255 _syscall_pre:
    256 	ldx	[%l1 + G1_OFF], %g1
    257 	call	pre_syscall			! abort = pre_syscall(arg0)
    258 	sth	%g1, [THREAD_REG + T_SYSNUM]
    259 
    260 	brnz,pn	%o0, _syscall_post		! did it abort?
    261 	nop
    262 	ldx	[%l1 + O0_OFF], %o0		! reload args
    263 	ldx	[%l1 + O1_OFF], %o1
    264 	ldx	[%l1 + O2_OFF], %o2
    265 	ldx	[%l1 + O3_OFF], %o3
    266 	ldx	[%l1 + O4_OFF], %o4
    267 	ba,pt	%xcc, 3b
    268 	ldx	[%l1 + O5_OFF], %o5
    269 
    270 	!
    271 	! Floating-point trap was pending at start of system call.
    272 	! Here with:
    273 	!	%l3 = mpcb_flags
    274 	!
    275 _syscall_fp:
    276 	andn	%l3, FP_TRAPPED, %l3
    277 	st	%l3, [%sp + STACK_BIAS + MPCB_FLAGS] 	! clear FP_TRAPPED
    278 	jmp	%l0 + 8				! return to user_rtt
    279 	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
    280 
    281 	!
    282 	! illegal system call - syscall number out of range
    283 	!
    284 _syscall_ill:
    285 	call	nosys
    286 	nop
    287 	!
    288 	! Post-syscall with special processing needed.
    289 	!
    290 _syscall_post:
    291 	call	post_syscall			! post_syscall(rvals)
    292 	nop
    293 	jmp	%l0 + 8				! return to user_rtt
    294 	nop
    295 	SET_SIZE(syscall_trap)
    296 #endif	/* lint */
    297 
    298 #if defined(lint) || defined(__lint)
    299 
    300 void
    301 syscall_trap32(void)	/* for tags only - trap handler - not called from C */
    302 {}
    303 
    304 #else /* lint */
    305 
    306 /*
    307  * System call trap handler for ILP32 processes.
    308  *
    309  * We branch here from sys_trap when a system call occurs.
    310  *
    311  * Entry:
    312  *	%o0 = regs
    313  *
    314  * Usage:
    315  *	%l0 = saved return address
    316  *	%l1 = saved regs
    317  *	%l2 = lwp
    318  */
    319 	ENTRY_NP(syscall_trap32)
    320 	ldx	[THREAD_REG + T_CPU], %g1	! get cpu pointer
    321 	mov	%o7, %l0			! save return addr
    322 
    323 	!
    324 	! If the trapping thread has the address mask bit clear, then it's
    325 	!   a 64-bit process, and has no business calling 32-bit syscalls.
    326 	!
    327 	ldx	[%o0 + TSTATE_OFF], %l1		! saved %tstate.am is that
    328 	andcc	%l1, TSTATE_AM, %l1		!   of the trapping proc
    329 	be,pn	%xcc, _syscall_ill32		!
    330 	  mov	%o0, %l1			! save reg pointer
    331 	srl	%i0, 0, %o0			! copy 1st arg, clear high bits
    332 	srl	%i1, 0, %o1			! copy 2nd arg, clear high bits
    333 	ldx	[%g1 + CPU_STATS_SYS_SYSCALL], %g2
    334 	inc	%g2				! cpu_stats.sys.syscall++
    335 	stx	%g2, [%g1 + CPU_STATS_SYS_SYSCALL]
    336 
    337 	!
    338 	! Set new state for LWP
    339 	!
    340 	ldx	[THREAD_REG + T_LWP], %l2
    341 	mov	LWP_SYS, %g3
    342 	srl	%i2, 0, %o2			! copy 3rd arg, clear high bits
    343 	stb	%g3, [%l2 + LWP_STATE]
    344 	srl	%i3, 0, %o3			! copy 4th arg, clear high bits
    345 	ldx	[%l2 + LWP_RU_SYSC], %g2	! pesky statistics
    346 	srl	%i4, 0, %o4			! copy 5th arg, clear high bits
    347 	addx	%g2, 1, %g2
    348 	stx	%g2, [%l2 + LWP_RU_SYSC]
    349 	srl	%i5, 0, %o5			! copy 6th arg, clear high bits
    350 	! args for direct syscalls now set up
    351 
    352 #ifdef TRAPTRACE
    353 	!
    354 	! make trap trace entry - helps in debugging
    355 	!
    356 	rdpr	%pstate, %l3
    357 	andn	%l3, PSTATE_IE | PSTATE_AM, %g3
    358 	wrpr	%g0, %g3, %pstate		! disable interrupt
    359 	TRACE_PTR(%g3, %g2)			! get trace pointer
    360 	GET_TRACE_TICK(%g1)
    361 	stxa	%g1, [%g3 + TRAP_ENT_TICK]%asi
    362 	ldx	[%l1 + G1_OFF], %g1		! get syscall code
    363 	TRACE_SAVE_TL_VAL(%g3, %g1)
    364 	TRACE_SAVE_GL_VAL(%g3, %g0)
    365 	set	TT_SC_ENTR, %g2
    366 	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
    367 	stxa	%g7, [%g3 + TRAP_ENT_TSTATE]%asi ! save thread in tstate space
    368 	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
    369 	stna	%o0, [%g3 + TRAP_ENT_F1]%asi
    370 	stna	%o1, [%g3 + TRAP_ENT_F2]%asi
    371 	stna	%o2, [%g3 + TRAP_ENT_F3]%asi
    372 	stna	%o3, [%g3 + TRAP_ENT_F4]%asi
    373 	stna	%o4, [%g3 + TRAP_ENT_TPC]%asi
    374 	stna	%o5, [%g3 + TRAP_ENT_TR]%asi
    375 	TRACE_NEXT(%g3, %g2, %g1)		! set new trace pointer
    376 	wrpr	%g0, %l3, %pstate		! enable interrupt
    377 #endif /* TRAPTRACE */
    378 
    379 	!
    380 	! Test for pre-system-call handling
    381 	!
    382 	ldub	[THREAD_REG + T_PRE_SYS], %g3	! pre-syscall proc?
    383 #ifdef SYSCALLTRACE
    384 	sethi	%hi(syscalltrace), %g4
    385 	ld	[%g4 + %lo(syscalltrace)], %g4
    386 	orcc	%g3, %g4, %g0			! pre_syscall OR syscalltrace?
    387 #else
    388 	tst	%g3				! is pre_syscall flag set?
    389 #endif /* SYSCALLTRACE */
    390 	bnz,pn	%icc, _syscall_pre32		! yes - pre_syscall needed
    391 	  nop
    392 
    393 	! Fast path invocation of new_mstate
    394 	mov	LMS_USER, %o0
    395 	call 	syscall_mstate
    396 	mov	LMS_SYSTEM, %o1
    397 
    398  	lduw	[%l1 + O0_OFF + 4], %o0		! reload 32-bit args
    399 	lduw	[%l1 + O1_OFF + 4], %o1
    400 	lduw	[%l1 + O2_OFF + 4], %o2
    401 	lduw	[%l1 + O3_OFF + 4], %o3
    402 	lduw	[%l1 + O4_OFF + 4], %o4
    403 	lduw	[%l1 + O5_OFF + 4], %o5
    404 
    405 	! lwp_arg now set up
    406 3:
    407 	!
    408 	! Call the handler.  The %o's have been set up.
    409 	!
    410 	lduw	[%l1 + G1_OFF + 4], %g1		! get 32-bit code
    411 	set	sysent32, %g3			! load address of vector table
    412 	cmp	%g1, NSYSCALL			! check range
    413 	sth	%g1, [THREAD_REG + T_SYSNUM]	! save syscall code
    414 	bgeu,pn	%ncc, _syscall_ill32
    415 	  sll	%g1, SYSENT_SHIFT, %g4		! delay - get index
    416 	add	%g3, %g4, %g5			! g5 = addr of sysentry
    417 	ldx	[%g5 + SY_CALLC], %g3		! load system call handler
    418 
    419 	brnz,a,pt %g1, 4f			! check for indir()
    420 	mov	%g5, %l4			! save addr of sysentry
    421 	!
    422 	! Yuck.  If %g1 is zero, that means we're doing a syscall() via the
    423 	! indirect system call.  That means we have to check the
    424 	! flags of the targetted system call, not the indirect system call
    425 	! itself.  See return value handling code below.
    426 	!
    427 	set	sysent32, %l4			! load address of vector table
    428 	cmp	%o0, NSYSCALL			! check range
    429 	bgeu,pn	%ncc, 4f			! out of range, let C handle it
    430 	  sll	%o0, SYSENT_SHIFT, %g4		! delay - get index
    431 	add	%g4, %l4, %l4			! compute & save addr of sysent
    432 4:
    433 	call	%g3				! call system call handler
    434 	nop
    435 
    436 	!
    437 	! If handler returns long long then we need to split the 64 bit
    438 	! return value in %o0 into %o0 and %o1 for ILP32 clients.
    439 	!
    440 	lduh    [%l4 + SY_FLAGS], %g4           ! load sy_flags
    441 	andcc	%g4, SE_64RVAL | SE_32RVAL2, %g0 ! check for 64-bit return
    442 	bz,a,pt	%xcc, 5f
    443 	  srl	%o0, 0, %o0			! 32-bit only
    444 	srl	%o0, 0, %o1			! lower 32 bits into %o1
    445 	srlx	%o0, 32, %o0			! upper 32 bits into %o0
    446 5:
    447 
    448 #ifdef TRAPTRACE
    449 	!
    450 	! make trap trace entry for return - helps in debugging
    451 	!
    452 	rdpr	%pstate, %g5
    453 	andn	%g5, PSTATE_IE | PSTATE_AM, %g4
    454 	wrpr	%g0, %g4, %pstate		! disable interrupt
    455 	TRACE_PTR(%g4, %g2)			! get trace pointer
    456 	GET_TRACE_TICK(%g2)
    457 	stxa	%g2, [%g4 + TRAP_ENT_TICK]%asi
    458 	lduh	[THREAD_REG + T_SYSNUM], %g2
    459 	TRACE_SAVE_TL_VAL(%g4, %g2)
    460 	TRACE_SAVE_GL_VAL(%g4, %g0)
    461 	mov	TT_SC_RET, %g2			! system call return code
    462 	stha	%g2, [%g4 + TRAP_ENT_TT]%asi
    463 	ldx	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
    464 	stna	%g2, [%g4 + TRAP_ENT_TPC]%asi
    465 	ldx	[%l1 + TSTATE_OFF], %g2		! get saved tstate
    466 	stxa	%g2, [%g4 + TRAP_ENT_TSTATE]%asi
    467 	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
    468 	stna	THREAD_REG, [%g4 + TRAP_ENT_TR]%asi
    469 	stna	%o0, [%g4 + TRAP_ENT_F1]%asi
    470 	stna	%o1, [%g4 + TRAP_ENT_F2]%asi
    471 	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
    472 	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
    473 	TRACE_NEXT(%g4, %g2, %g3)		! set new trace pointer
    474 	wrpr	%g0, %g5, %pstate		! enable interrupt
    475 #endif /* TRAPTRACE */
    476 	!
    477 	! Check for post-syscall processing.
    478 	! This tests all members of the union containing t_astflag, t_post_sys,
    479 	! and t_sig_check with one test.
    480 	!
    481 	ld	[THREAD_REG + T_POST_SYS_AST], %g1
    482 #ifdef SYSCALLTRACE
    483 	sethi	%hi(syscalltrace), %g4
    484 	ld	[%g4 + %lo(syscalltrace)], %g4
    485 	orcc	%g4, %g1, %g0			! OR in syscalltrace
    486 #else
    487 	tst	%g1				! need post-processing?
    488 #endif /* SYSCALLTRACE */
    489 	bnz,pn	%icc, _syscall_post32		! yes - post_syscall or AST set
    490 	mov	LWP_USER, %g1
    491 	stb	%g1, [%l2 + LWP_STATE]		! set lwp_state
    492 	stx	%o0, [%l1 + O0_OFF]		! set rp->r_o0
    493 	stx	%o1, [%l1 + O1_OFF]		! set rp->r_o1
    494 	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
    495 	ldx	[%l1 + TSTATE_OFF], %g1		! get saved tstate
    496 	ldx	[%l1 + nPC_OFF], %g2		! get saved npc (new pc)
    497 	mov	CCR_IC, %g3
    498 	sllx	%g3, TSTATE_CCR_SHIFT, %g3
    499 	add	%g2, 4, %g4			! calc new npc
    500 	andn	%g1, %g3, %g1			! clear carry bit for no error
    501 	stx	%g2, [%l1 + PC_OFF]
    502 	stx	%g4, [%l1 + nPC_OFF]
    503 	stx	%g1, [%l1 + TSTATE_OFF]
    504 
    505 	! fast path outbound microstate accounting call
    506 	mov	LMS_SYSTEM, %o0
    507 	call 	syscall_mstate
    508 	mov	LMS_USER, %o1
    509 
    510 	jmp	%l0 + 8
    511 	 nop
    512 
    513 
    514 _syscall_pre32:
    515 	ldx	[%l1 + G1_OFF], %g1
    516 	call	pre_syscall			! abort = pre_syscall(arg0)
    517 	sth	%g1, [THREAD_REG + T_SYSNUM]
    518 
    519 	brnz,pn	%o0, _syscall_post32		! did it abort?
    520 	nop
    521  	lduw	[%l1 + O0_OFF + 4], %o0		! reload 32-bit args
    522 	lduw	[%l1 + O1_OFF + 4], %o1
    523 	lduw	[%l1 + O2_OFF + 4], %o2
    524 	lduw	[%l1 + O3_OFF + 4], %o3
    525 	lduw	[%l1 + O4_OFF + 4], %o4
    526 	ba,pt	%xcc, 3b
    527 	lduw	[%l1 + O5_OFF + 4], %o5
    528 
    529 	!
    530 	! Floating-point trap was pending at start of system call.
    531 	! Here with:
    532 	!	%l3 = mpcb_flags
    533 	!
    534 _syscall_fp32:
    535 	andn	%l3, FP_TRAPPED, %l3
    536 	st	%l3, [%sp + STACK_BIAS + MPCB_FLAGS] 	! clear FP_TRAPPED
    537 	jmp	%l0 + 8				! return to user_rtt
    538 	clrh	[THREAD_REG + T_SYSNUM]		! clear syscall code
    539 
    540 	!
    541 	! illegal system call - syscall number out of range
    542 	!
    543 _syscall_ill32:
    544 	call	nosys
    545 	nop
    546 	!
    547 	! Post-syscall with special processing needed.
    548 	!
    549 _syscall_post32:
    550 	call	post_syscall			! post_syscall(rvals)
    551 	nop
    552 	jmp	%l0 + 8				! return to user_rtt
    553 	nop
    554 	SET_SIZE(syscall_trap32)
    555 
    556 #endif /* lint */
    557 
    558 
    559 /*
    560  * lwp_rtt - start execution in newly created LWP.
    561  *	Here with t_post_sys set by lwp_create, and lwp_eosys == JUSTRETURN,
    562  *	so that post_syscall() will run and the registers will
    563  *	simply be restored.
    564  *	This must go out through sys_rtt instead of syscall_rtt.
    565  */
    566 #if defined(lint) || defined(__lint)
    567 
    568 void
    569 lwp_rtt_initial(void)
    570 {}
    571 
    572 void
    573 lwp_rtt(void)
    574 {}
    575 
    576 #else	/* lint */
    577 	ENTRY_NP(lwp_rtt_initial)
    578 	ldn	[THREAD_REG + T_STACK], %l7
    579 	call	__dtrace_probe___proc_start
    580 	sub	%l7, STACK_BIAS, %sp
    581 	ba,a,pt	%xcc, 0f
    582 
    583 	ENTRY_NP(lwp_rtt)
    584 	ldn	[THREAD_REG + T_STACK], %l7
    585 	sub	%l7, STACK_BIAS, %sp
    586 0:
    587 	call	__dtrace_probe___proc_lwp__start
    588 	nop
    589 	call	dtrace_systrace_rtt
    590 	add	%sp, REGOFF + STACK_BIAS, %l7
    591 	ldx	[%l7 + O0_OFF], %o0
    592 	call	post_syscall
    593 	ldx	[%l7 + O1_OFF], %o1
    594 	ba,a,pt	%xcc, user_rtt
    595 	SET_SIZE(lwp_rtt)
    596 	SET_SIZE(lwp_rtt_initial)
    597 
    598 #endif	/* lint */
    599