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