2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include <kern/task.h>
27 #include <kern/thread.h>
28 #include <kern/thread_act.h>
29 #include <kern/assert.h>
30 #include <kern/clock.h>
31 #include <mach/machine/thread_status.h>
32 #include <ppc/savearea.h>
34 #include <sys/kernel.h>
37 #include <sys/syscall.h>
38 #include <sys/systm.h>
40 #include <sys/errno.h>
41 #include <sys/ktrace.h>
42 #include <sys/kdebug.h>
43 #include <sys/kern_audit.h>
50 extern struct savearea
*
54 extern void enter_funnel_section(funnel_t
*funnel_lock
);
55 extern void exit_funnel_section(void);
58 * Function: unix_syscall
60 * Inputs: regs - pointer to Process Control Block
69 thread_act_t thread_act
;
70 struct uthread
*uthread
;
78 flavor
= (((unsigned int)regs
->save_r0
) == NULL
)? 1: 0;
85 if (kdebug_enable
&& (code
!= 180)) {
87 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
88 regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, regs
->save_r7
, 0);
90 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
91 regs
->save_r3
, regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, 0);
93 thread_act
= current_act();
94 uthread
= get_bsdthread_info(thread_act
);
96 if (!(uthread
->uu_flag
& P_VFORK
))
97 proc
= (struct proc
*)get_bsdtask_info(current_task());
99 proc
= current_proc();
101 uthread
->uu_ar0
= (int *)regs
;
103 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
106 if (callp
->sy_narg
> 8)
107 panic("unix_syscall: max arg count exceeded");
110 if (callp
->sy_narg
!= 0) {
112 uthread
->uu_arg
[0] = regs
->save_r3
;
113 uthread
->uu_arg
[1] = regs
->save_r4
;
114 uthread
->uu_arg
[2] = regs
->save_r5
;
115 uthread
->uu_arg
[3] = regs
->save_r6
;
116 uthread
->uu_arg
[4] = regs
->save_r7
;
117 uthread
->uu_arg
[5] = regs
->save_r8
;
118 uthread
->uu_arg
[6] = regs
->save_r9
;
119 uthread
->uu_arg
[7] = regs
->save_r10
;
121 uthread
->uu_arg
[0] = regs
->save_r4
;
122 uthread
->uu_arg
[1] = regs
->save_r5
;
123 uthread
->uu_arg
[2] = regs
->save_r6
;
124 uthread
->uu_arg
[3] = regs
->save_r7
;
125 uthread
->uu_arg
[4] = regs
->save_r8
;
126 uthread
->uu_arg
[5] = regs
->save_r9
;
127 uthread
->uu_arg
[7] = regs
->save_r10
;
131 funnel_type
= (int)callp
->sy_funnel
;
132 if (funnel_type
== KERNEL_FUNNEL
)
133 enter_funnel_section(kernel_flock
);
134 else if (funnel_type
== NETWORK_FUNNEL
)
135 enter_funnel_section(network_flock
);
137 uthread
->uu_rval
[0] = 0;
140 * r4 is volatile, if we set it to regs->save_r4 here the child
141 * will have parents r4 after execve
143 uthread
->uu_rval
[1] = 0;
148 * PPC runtime calls cerror after every unix system call, so
149 * assume no error and adjust the "pc" to skip this call.
150 * It will be set back to the cerror call if an error is detected.
152 regs
->save_srr0
+= 4;
154 if (KTRPOINT(proc
, KTR_SYSCALL
))
155 ktrsyscall(proc
, code
, callp
->sy_narg
, uthread
->uu_arg
, funnel_type
);
157 AUDIT_CMD(audit_syscall_enter(code
, proc
, uthread
));
158 error
= (*(callp
->sy_call
))(proc
, (void *)uthread
->uu_arg
, &(uthread
->uu_rval
[0]));
159 AUDIT_CMD(audit_syscall_exit(error
, proc
, uthread
));
161 regs
= find_user_regs(thread_act
);
163 if (error
== ERESTART
) {
164 regs
->save_srr0
-= 8;
165 } else if (error
!= EJUSTRETURN
) {
167 regs
->save_r3
= (long long)error
;
168 /* set the "pc" to execute cerror routine */
169 regs
->save_srr0
-= 4;
170 } else { /* (not error) */
171 regs
->save_r3
= uthread
->uu_rval
[0];
172 regs
->save_r4
= uthread
->uu_rval
[1];
175 /* else (error == EJUSTRETURN) { nothing } */
177 if (KTRPOINT(proc
, KTR_SYSRET
))
178 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
180 exit_funnel_section();
182 if (kdebug_enable
&& (code
!= 180)) {
183 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
184 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
187 thread_exception_return();
191 unix_syscall_return(error
)
193 thread_act_t thread_act
;
194 struct uthread
*uthread
;
196 struct savearea
*regs
;
198 struct sysent
*callp
;
201 thread_act
= current_act();
202 proc
= current_proc();
203 uthread
= get_bsdthread_info(thread_act
);
205 regs
= find_user_regs(thread_act
);
208 * Get index into sysent table
210 if (error
== ERESTART
) {
211 regs
->save_srr0
-= 8;
212 } else if (error
!= EJUSTRETURN
) {
214 regs
->save_r3
= (long long)error
;
215 /* set the "pc" to execute cerror routine */
216 regs
->save_srr0
-= 4;
217 } else { /* (not error) */
218 regs
->save_r3
= uthread
->uu_rval
[0];
219 regs
->save_r4
= uthread
->uu_rval
[1];
222 /* else (error == EJUSTRETURN) { nothing } */
224 if (regs
->save_r0
!= NULL
)
225 code
= regs
->save_r0
;
227 code
= regs
->save_r3
;
229 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
231 funnel_type
= (int)callp
->sy_funnel
;
233 if (KTRPOINT(proc
, KTR_SYSRET
))
234 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
236 exit_funnel_section();
238 if (kdebug_enable
&& (code
!= 180)) {
239 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
240 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
243 thread_exception_return();
248 * Time of day and interval timer support.
250 * These routines provide the kernel entry points to get and set
251 * the time-of-day and per-process interval timers. Subroutines
252 * here provide support for adding and subtracting timeval structures
253 * and decrementing interval timers, optionally reloading the interval
254 * timers when they expire.
256 struct gettimeofday_args
{
258 struct timezone
*tzp
;
260 /* NOTE THIS implementation is for ppc architectures only.
261 * It is infrequently called, since the commpage intercepts
262 * most calls in user mode.
265 ppc_gettimeofday(p
, uap
, retval
)
267 register struct gettimeofday_args
*uap
;
273 clock_gettimeofday(&retval
[0], &retval
[1]);
277 extern simple_lock_data_t tz_slock
;
279 usimple_lock(&tz_slock
);
281 usimple_unlock(&tz_slock
);
282 error
= copyout((caddr_t
)<z
, (caddr_t
)uap
->tzp
, sizeof (tz
));