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