2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <kern/task.h>
24 #include <kern/thread.h>
25 #include <kern/thread_act.h>
26 #include <kern/assert.h>
27 #include <kern/clock.h>
28 #include <mach/machine/thread_status.h>
29 #include <ppc/savearea.h>
31 #include <sys/kernel.h>
34 #include <sys/syscall.h>
35 #include <sys/systm.h>
37 #include <sys/errno.h>
38 #include <sys/ktrace.h>
39 #include <sys/kdebug.h>
41 #include <bsm/audit_kernel.h>
48 extern struct savearea
*
52 extern void enter_funnel_section(funnel_t
*funnel_lock
);
53 extern void exit_funnel_section(void);
56 * Function: unix_syscall
58 * Inputs: regs - pointer to Process Control Block
67 thread_act_t thread_act
;
68 struct uthread
*uthread
;
76 flavor
= (((unsigned int)regs
->save_r0
) == NULL
)? 1: 0;
83 if (kdebug_enable
&& (code
!= 180)) {
85 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
86 regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, regs
->save_r7
, 0);
88 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_START
,
89 regs
->save_r3
, regs
->save_r4
, regs
->save_r5
, regs
->save_r6
, 0);
91 thread_act
= current_act();
92 uthread
= get_bsdthread_info(thread_act
);
94 if (!(uthread
->uu_flag
& P_VFORK
))
95 proc
= (struct proc
*)get_bsdtask_info(current_task());
97 proc
= current_proc();
99 uthread
->uu_ar0
= (int *)regs
;
101 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
104 if (callp
->sy_narg
> 8)
105 panic("unix_syscall: max arg count exceeded");
108 if (callp
->sy_narg
!= 0) {
110 uthread
->uu_arg
[0] = regs
->save_r3
;
111 uthread
->uu_arg
[1] = regs
->save_r4
;
112 uthread
->uu_arg
[2] = regs
->save_r5
;
113 uthread
->uu_arg
[3] = regs
->save_r6
;
114 uthread
->uu_arg
[4] = regs
->save_r7
;
115 uthread
->uu_arg
[5] = regs
->save_r8
;
116 uthread
->uu_arg
[6] = regs
->save_r9
;
117 uthread
->uu_arg
[7] = regs
->save_r10
;
119 uthread
->uu_arg
[0] = regs
->save_r4
;
120 uthread
->uu_arg
[1] = regs
->save_r5
;
121 uthread
->uu_arg
[2] = regs
->save_r6
;
122 uthread
->uu_arg
[3] = regs
->save_r7
;
123 uthread
->uu_arg
[4] = regs
->save_r8
;
124 uthread
->uu_arg
[5] = regs
->save_r9
;
125 uthread
->uu_arg
[7] = regs
->save_r10
;
129 funnel_type
= (int)callp
->sy_funnel
;
130 if (funnel_type
== KERNEL_FUNNEL
)
131 enter_funnel_section(kernel_flock
);
132 else if (funnel_type
== NETWORK_FUNNEL
)
133 enter_funnel_section(network_flock
);
135 uthread
->uu_rval
[0] = 0;
138 * r4 is volatile, if we set it to regs->save_r4 here the child
139 * will have parents r4 after execve
141 uthread
->uu_rval
[1] = 0;
146 * PPC runtime calls cerror after every unix system call, so
147 * assume no error and adjust the "pc" to skip this call.
148 * It will be set back to the cerror call if an error is detected.
150 regs
->save_srr0
+= 4;
152 if (KTRPOINT(proc
, KTR_SYSCALL
))
153 ktrsyscall(proc
, code
, callp
->sy_narg
, uthread
->uu_arg
, funnel_type
);
155 AUDIT_SYSCALL_ENTER(code
, proc
, uthread
);
156 error
= (*(callp
->sy_call
))(proc
, (void *)uthread
->uu_arg
, &(uthread
->uu_rval
[0]));
157 AUDIT_SYSCALL_EXIT(error
, proc
, uthread
);
159 regs
= find_user_regs(thread_act
);
161 if (error
== ERESTART
) {
162 regs
->save_srr0
-= 8;
163 } else if (error
!= EJUSTRETURN
) {
165 regs
->save_r3
= (long long)error
;
166 /* set the "pc" to execute cerror routine */
167 regs
->save_srr0
-= 4;
168 } else { /* (not error) */
169 regs
->save_r3
= uthread
->uu_rval
[0];
170 regs
->save_r4
= uthread
->uu_rval
[1];
173 /* else (error == EJUSTRETURN) { nothing } */
175 if (KTRPOINT(proc
, KTR_SYSRET
))
176 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
178 exit_funnel_section();
180 if (kdebug_enable
&& (code
!= 180)) {
181 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
182 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
185 thread_exception_return();
189 unix_syscall_return(error
)
191 thread_act_t thread_act
;
192 struct uthread
*uthread
;
194 struct savearea
*regs
;
196 struct sysent
*callp
;
199 thread_act
= current_act();
200 proc
= current_proc();
201 uthread
= get_bsdthread_info(thread_act
);
203 regs
= find_user_regs(thread_act
);
206 * Get index into sysent table
208 if (error
== ERESTART
) {
209 regs
->save_srr0
-= 8;
210 } else if (error
!= EJUSTRETURN
) {
212 regs
->save_r3
= (long long)error
;
213 /* set the "pc" to execute cerror routine */
214 regs
->save_srr0
-= 4;
215 } else { /* (not error) */
216 regs
->save_r3
= uthread
->uu_rval
[0];
217 regs
->save_r4
= uthread
->uu_rval
[1];
220 /* else (error == EJUSTRETURN) { nothing } */
222 if (regs
->save_r0
!= NULL
)
223 code
= regs
->save_r0
;
225 code
= regs
->save_r3
;
227 callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
229 funnel_type
= (int)callp
->sy_funnel
;
231 if (KTRPOINT(proc
, KTR_SYSRET
))
232 ktrsysret(proc
, code
, error
, uthread
->uu_rval
[0], funnel_type
);
234 exit_funnel_section();
236 if (kdebug_enable
&& (code
!= 180)) {
237 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC
, code
) | DBG_FUNC_END
,
238 error
, uthread
->uu_rval
[0], uthread
->uu_rval
[1], 0, 0);
241 thread_exception_return();
246 * Time of day and interval timer support.
248 * These routines provide the kernel entry points to get and set
249 * the time-of-day and per-process interval timers. Subroutines
250 * here provide support for adding and subtracting timeval structures
251 * and decrementing interval timers, optionally reloading the interval
252 * timers when they expire.
254 struct gettimeofday_args
{
256 struct timezone
*tzp
;
258 /* NOTE THIS implementation is for ppc architectures only.
259 * It is infrequently called, since the commpage intercepts
260 * most calls in user mode.
263 ppc_gettimeofday(p
, uap
, retval
)
265 register struct gettimeofday_args
*uap
;
271 clock_gettimeofday(&retval
[0], &retval
[1]);
275 extern simple_lock_data_t tz_slock
;
277 usimple_lock(&tz_slock
);
279 usimple_unlock(&tz_slock
);
280 error
= copyout((caddr_t
)<z
, (caddr_t
)uap
->tzp
, sizeof (tz
));