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 */