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 <mach/machine/thread_status.h>
31 #include <ppc/savearea.h>
33 #include <sys/kernel.h>
36 #include <sys/syscall.h>
37 #include <sys/systm.h>
39 #include <sys/errno.h>
40 #include <sys/ktrace.h>
41 #include <sys/kdebug.h>
48 extern struct savearea
*
52 extern enter_funnel_section(funnel_t
*funnel_lock
);
53 extern exit_funnel_section(funnel_t
*funnel_lock
);
56 * Function: unix_syscall
58 * Inputs: regs - pointer to Process Control Block
67 thread_act_t thread_act
;
68 struct uthread
*uthread
;
76 thread_act
= current_act();
77 uthread
= get_bsdthread_info(thread_act
);
79 if (!(uthread
->uu_flag
& P_VFORK
))
80 proc
= (struct proc
*)get_bsdtask_info(current_task());
82 proc
= current_proc();
84 flavor
= (regs
->save_r0
== NULL
)? 1: 0;
86 uthread
->uu_ar0
= (int *)regs
;
93 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
96 if (callp
->sy_narg
> 8)
97 panic("unix_syscall: max arg count exceeded");
100 if (callp
->sy_narg
!= 0) {
102 uthread
->uu_arg
[0] = regs
->save_r3
;
103 uthread
->uu_arg
[1] = regs
->save_r4
;
104 uthread
->uu_arg
[2] = regs
->save_r5
;
105 uthread
->uu_arg
[3] = regs
->save_r6
;
106 uthread
->uu_arg
[4] = regs
->save_r7
;
107 uthread
->uu_arg
[5] = regs
->save_r8
;
108 uthread
->uu_arg
[6] = regs
->save_r9
;
109 uthread
->uu_arg
[7] = regs
->save_r10
;
111 uthread
->uu_arg
[0] = regs
->save_r4
;
112 uthread
->uu_arg
[1] = regs
->save_r5
;
113 uthread
->uu_arg
[2] = regs
->save_r6
;
114 uthread
->uu_arg
[3] = regs
->save_r7
;
115 uthread
->uu_arg
[4] = regs
->save_r8
;
116 uthread
->uu_arg
[5] = regs
->save_r9
;
117 uthread
->uu_arg
[7] = regs
->save_r10
;
121 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
123 if (kdebug_enable
&& (code
!= 180)) {
125 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
126 regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, regs
->save_r7
, 0);
128 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
129 regs
->save_r3
, regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, 0);
132 funnel_type
= (int)callp
->sy_funnel
;
133 if(funnel_type
== KERNEL_FUNNEL
)
134 enter_funnel_section(kernel_flock
);
135 else if (funnel_type
== NETWORK_FUNNEL
)
136 enter_funnel_section(network_flock
);
139 uthread
->uu_rval
[0] = 0;
142 * r4 is volatile, if we set it to regs->save_r4 here the child
143 * will have parents r4 after execve
145 uthread
->uu_rval
[1] = 0;
150 * PPC runtime calls cerror after every unix system call, so
151 * assume no error and adjust the "pc" to skip this call.
152 * It will be set back to the cerror call if an error is detected.
154 regs
->save_srr0
+= 4;
156 if (KTRPOINT(proc
, KTR_SYSCALL
))
157 ktrsyscall(proc
, code
, callp
->sy_narg
, uthread
->uu_arg
, funnel_type
);
159 error
= (*(callp
->sy_call
))(proc
, (void *)uthread
->uu_arg
, &(uthread
->uu_rval
[0]));
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
= 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 if(funnel_type
== KERNEL_FUNNEL
)
181 exit_funnel_section(kernel_flock
);
182 else if (funnel_type
== NETWORK_FUNNEL
)
183 exit_funnel_section(network_flock
);
185 if (kdebug_enable
&& (code
!= 180)) {
186 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
187 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
190 thread_exception_return();
194 unix_syscall_return(error
)
196 thread_act_t thread_act
;
197 struct uthread
*uthread
;
199 struct savearea
*regs
;
201 struct sysent
*callp
;
204 thread_act
= current_act();
205 proc
= current_proc();
206 uthread
= get_bsdthread_info(thread_act
);
208 regs
= find_user_regs(thread_act
);
211 * Get index into sysent table
213 if (error
== ERESTART
) {
214 regs
->save_srr0
-= 8;
215 } else if (error
!= EJUSTRETURN
) {
217 regs
->save_r3
= error
;
218 /* set the "pc" to execute cerror routine */
219 regs
->save_srr0
-= 4;
220 } else { /* (not error) */
221 regs
->save_r3
= uthread
->uu_rval
[0];
222 regs
->save_r4
= uthread
->uu_rval
[1];
225 /* else (error == EJUSTRETURN) { nothing } */
227 if (regs
->save_r0
!= NULL
)
228 code
= regs
->save_r0
;
230 code
= regs
->save_r3
;
232 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
234 funnel_type
= (int)callp
->sy_funnel
;
236 if (KTRPOINT(proc
, KTR_SYSRET
))
237 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
239 if(funnel_type
== KERNEL_FUNNEL
)
240 exit_funnel_section(kernel_flock
);
241 else if (funnel_type
== NETWORK_FUNNEL
)
242 exit_funnel_section(network_flock
);
244 if (kdebug_enable
&& (code
!= 180)) {
245 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
246 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
249 thread_exception_return();
254 * Time of day and interval timer support.
256 * These routines provide the kernel entry points to get and set
257 * the time-of-day and per-process interval timers. Subroutines
258 * here provide support for adding and subtracting timeval structures
259 * and decrementing interval timers, optionally reloading the interval
260 * timers when they expire.
262 struct gettimeofday_args
{
264 struct timezone
*tzp
;
266 /* NOTE THIS implementation is for ppc architectures only */
268 ppc_gettimeofday(p
, uap
, retval
)
270 register struct gettimeofday_args
*uap
;
276 //struct savearea *child_state;
277 extern simple_lock_data_t tz_slock
;
281 retval
[0] = atv
.tv_sec
;
282 retval
[1] = atv
.tv_usec
;
286 usimple_lock(&tz_slock
);
288 usimple_unlock(&tz_slock
);
289 error
= copyout((caddr_t
)<z
, (caddr_t
)uap
->tzp
,