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