2 * Copyright (c) 2000-2001 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>
49 extern struct savearea
*
53 extern void enter_funnel_section(funnel_t
*funnel_lock
);
54 extern void exit_funnel_section(void);
57 * Function: unix_syscall
59 * Inputs: regs - pointer to Process Control Block
68 thread_act_t thread_act
;
69 struct uthread
*uthread
;
77 thread_act
= current_act();
78 uthread
= get_bsdthread_info(thread_act
);
80 if (!(uthread
->uu_flag
& P_VFORK
))
81 proc
= (struct proc
*)get_bsdtask_info(current_task());
83 proc
= current_proc();
85 flavor
= (((unsigned int)regs
->save_r0
) == NULL
)? 1: 0;
87 uthread
->uu_ar0
= (int *)regs
;
94 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
97 if (callp
->sy_narg
> 8)
98 panic("unix_syscall: max arg count exceeded");
101 if (callp
->sy_narg
!= 0) {
103 uthread
->uu_arg
[0] = regs
->save_r3
;
104 uthread
->uu_arg
[1] = regs
->save_r4
;
105 uthread
->uu_arg
[2] = regs
->save_r5
;
106 uthread
->uu_arg
[3] = regs
->save_r6
;
107 uthread
->uu_arg
[4] = regs
->save_r7
;
108 uthread
->uu_arg
[5] = regs
->save_r8
;
109 uthread
->uu_arg
[6] = regs
->save_r9
;
110 uthread
->uu_arg
[7] = regs
->save_r10
;
112 uthread
->uu_arg
[0] = regs
->save_r4
;
113 uthread
->uu_arg
[1] = regs
->save_r5
;
114 uthread
->uu_arg
[2] = regs
->save_r6
;
115 uthread
->uu_arg
[3] = regs
->save_r7
;
116 uthread
->uu_arg
[4] = regs
->save_r8
;
117 uthread
->uu_arg
[5] = regs
->save_r9
;
118 uthread
->uu_arg
[7] = regs
->save_r10
;
122 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
124 if (kdebug_enable
&& (code
!= 180)) {
126 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
127 regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, regs
->save_r7
, 0);
129 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
130 regs
->save_r3
, regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, 0);
133 funnel_type
= (int)callp
->sy_funnel
;
134 if(funnel_type
== KERNEL_FUNNEL
)
135 enter_funnel_section(kernel_flock
);
136 else if (funnel_type
== NETWORK_FUNNEL
)
137 enter_funnel_section(network_flock
);
140 uthread
->uu_rval
[0] = 0;
143 * r4 is volatile, if we set it to regs->save_r4 here the child
144 * will have parents r4 after execve
146 uthread
->uu_rval
[1] = 0;
151 * PPC runtime calls cerror after every unix system call, so
152 * assume no error and adjust the "pc" to skip this call.
153 * It will be set back to the cerror call if an error is detected.
155 regs
->save_srr0
+= 4;
157 if (KTRPOINT(proc
, KTR_SYSCALL
))
158 ktrsyscall(proc
, code
, callp
->sy_narg
, uthread
->uu_arg
, funnel_type
);
160 error
= (*(callp
->sy_call
))(proc
, (void *)uthread
->uu_arg
, &(uthread
->uu_rval
[0]));
162 regs
= find_user_regs(thread_act
);
164 if (error
== ERESTART
) {
165 regs
->save_srr0
-= 8;
166 } else if (error
!= EJUSTRETURN
) {
168 regs
->save_r3
= (long long)error
;
169 /* set the "pc" to execute cerror routine */
170 regs
->save_srr0
-= 4;
171 } else { /* (not error) */
172 regs
->save_r3
= uthread
->uu_rval
[0];
173 regs
->save_r4
= uthread
->uu_rval
[1];
176 /* else (error == EJUSTRETURN) { nothing } */
178 if (KTRPOINT(proc
, KTR_SYSRET
))
179 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
181 exit_funnel_section();
183 if (kdebug_enable
&& (code
!= 180)) {
184 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
185 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
188 thread_exception_return();
192 unix_syscall_return(error
)
194 thread_act_t thread_act
;
195 struct uthread
*uthread
;
197 struct savearea
*regs
;
199 struct sysent
*callp
;
202 thread_act
= current_act();
203 proc
= current_proc();
204 uthread
= get_bsdthread_info(thread_act
);
206 regs
= find_user_regs(thread_act
);
209 * Get index into sysent table
211 if (error
== ERESTART
) {
212 regs
->save_srr0
-= 8;
213 } else if (error
!= EJUSTRETURN
) {
215 regs
->save_r3
= (long long)error
;
216 /* set the "pc" to execute cerror routine */
217 regs
->save_srr0
-= 4;
218 } else { /* (not error) */
219 regs
->save_r3
= uthread
->uu_rval
[0];
220 regs
->save_r4
= uthread
->uu_rval
[1];
223 /* else (error == EJUSTRETURN) { nothing } */
225 if (regs
->save_r0
!= NULL
)
226 code
= regs
->save_r0
;
228 code
= regs
->save_r3
;
230 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
232 funnel_type
= (int)callp
->sy_funnel
;
234 if (KTRPOINT(proc
, KTR_SYSRET
))
235 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
237 exit_funnel_section();
239 if (kdebug_enable
&& (code
!= 180)) {
240 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
241 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
244 thread_exception_return();
249 * Time of day and interval timer support.
251 * These routines provide the kernel entry points to get and set
252 * the time-of-day and per-process interval timers. Subroutines
253 * here provide support for adding and subtracting timeval structures
254 * and decrementing interval timers, optionally reloading the interval
255 * timers when they expire.
257 struct gettimeofday_args
{
259 struct timezone
*tzp
;
261 /* NOTE THIS implementation is for ppc architectures only.
262 * It is infrequently called, since the commpage intercepts
263 * most calls in user mode.
266 ppc_gettimeofday(p
, uap
, retval
)
268 register struct gettimeofday_args
*uap
;
274 clock_gettimeofday(&retval
[0], &retval
[1]);
278 extern simple_lock_data_t tz_slock
;
280 usimple_lock(&tz_slock
);
282 usimple_unlock(&tz_slock
);
283 error
= copyout((caddr_t
)<z
, (caddr_t
)uap
->tzp
, sizeof (tz
));