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