]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/ppc/systemcalls.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / bsd / dev / ppc / systemcalls.c
CommitLineData
1c79356b 1/*
9bccf70c 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
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
13 * file.
14 *
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
9bccf70c
A
25
26#include <kern/task.h>
27#include <kern/thread.h>
28#include <kern/thread_act.h>
29#include <kern/assert.h>
d7e50217 30#include <kern/clock.h>
9bccf70c
A
31#include <mach/machine/thread_status.h>
32#include <ppc/savearea.h>
33
34#include <sys/kernel.h>
35#include <sys/vm.h>
36#include <sys/proc.h>
37#include <sys/syscall.h>
38#include <sys/systm.h>
39#include <sys/user.h>
40#include <sys/errno.h>
41#include <sys/ktrace.h>
42#include <sys/kdebug.h>
43
44extern void
45unix_syscall(
46 struct savearea *regs
47);
48
49extern struct savearea *
50find_user_regs(
51 thread_act_t act);
52
d7e50217
A
53extern void enter_funnel_section(funnel_t *funnel_lock);
54extern void exit_funnel_section(void);
9bccf70c 55
1c79356b 56/*
9bccf70c 57 * Function: unix_syscall
1c79356b 58 *
9bccf70c 59 * Inputs: regs - pointer to Process Control Block
1c79356b 60 *
9bccf70c 61 * Outputs: none
1c79356b 62 */
9bccf70c
A
63void
64unix_syscall(
65 struct savearea *regs
66)
67{
68 thread_act_t thread_act;
69 struct uthread *uthread;
70 struct proc *proc;
71 struct sysent *callp;
72 int error;
73 unsigned short code;
74 boolean_t flavor;
75 int funnel_type;
1c79356b 76
9bccf70c
A
77 thread_act = current_act();
78 uthread = get_bsdthread_info(thread_act);
1c79356b 79
9bccf70c
A
80 if (!(uthread->uu_flag & P_VFORK))
81 proc = (struct proc *)get_bsdtask_info(current_task());
82 else
83 proc = current_proc();
1c79356b 84
d7e50217 85 flavor = (((unsigned int)regs->save_r0) == NULL)? 1: 0;
1c79356b 86
9bccf70c 87 uthread->uu_ar0 = (int *)regs;
1c79356b 88
9bccf70c
A
89 if (flavor)
90 code = regs->save_r3;
91 else
92 code = regs->save_r0;
1c79356b 93
9bccf70c 94 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 95
9bccf70c
A
96#ifdef DEBUG
97 if (callp->sy_narg > 8)
98 panic("unix_syscall: max arg count exceeded");
99#endif
100
101 if (callp->sy_narg != 0) {
102 if ( !flavor) {
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;
111 } else {
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;
119 }
120 }
1c79356b 121
9bccf70c 122 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 123
9bccf70c
A
124 if (kdebug_enable && (code != 180)) {
125 if (flavor)
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);
128 else
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);
131 }
1c79356b 132
9bccf70c
A
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);
138
1c79356b 139
9bccf70c 140 uthread->uu_rval[0] = 0;
1c79356b 141
1c79356b 142 /*
9bccf70c
A
143 * r4 is volatile, if we set it to regs->save_r4 here the child
144 * will have parents r4 after execve
145 */
146 uthread->uu_rval[1] = 0;
1c79356b 147
9bccf70c 148 error = 0;
1c79356b 149
9bccf70c
A
150 /*
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.
154 */
155 regs->save_srr0 += 4;
1c79356b 156
9bccf70c
A
157 if (KTRPOINT(proc, KTR_SYSCALL))
158 ktrsyscall(proc, code, callp->sy_narg, uthread->uu_arg, funnel_type);
1c79356b 159
9bccf70c
A
160 error = (*(callp->sy_call))(proc, (void *)uthread->uu_arg, &(uthread->uu_rval[0]));
161
162 regs = find_user_regs(thread_act);
1c79356b 163
9bccf70c
A
164 if (error == ERESTART) {
165 regs->save_srr0 -= 8;
166 } else if (error != EJUSTRETURN) {
167 if (error) {
d7e50217 168 regs->save_r3 = (long long)error;
9bccf70c
A
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];
174 }
175 }
176 /* else (error == EJUSTRETURN) { nothing } */
1c79356b 177
9bccf70c
A
178 if (KTRPOINT(proc, KTR_SYSRET))
179 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
1c79356b 180
d7e50217 181 exit_funnel_section();
9bccf70c
A
182
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);
186 }
187
188 thread_exception_return();
189 /* NOTREACHED */
190}
191
192unix_syscall_return(error)
193{
194 thread_act_t thread_act;
195 struct uthread *uthread;
196 struct proc *proc;
197 struct savearea *regs;
198 unsigned short code;
199 struct sysent *callp;
200 int funnel_type;
201
202 thread_act = current_act();
203 proc = current_proc();
204 uthread = get_bsdthread_info(thread_act);
205
206 regs = find_user_regs(thread_act);
1c79356b
A
207
208 /*
9bccf70c
A
209 * Get index into sysent table
210 */
211 if (error == ERESTART) {
212 regs->save_srr0 -= 8;
213 } else if (error != EJUSTRETURN) {
214 if (error) {
d7e50217 215 regs->save_r3 = (long long)error;
9bccf70c
A
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];
221 }
222 }
223 /* else (error == EJUSTRETURN) { nothing } */
224
225 if (regs->save_r0 != NULL)
226 code = regs->save_r0;
227 else
228 code = regs->save_r3;
229
230 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
231
232 funnel_type = (int)callp->sy_funnel;
233
234 if (KTRPOINT(proc, KTR_SYSRET))
235 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
236
d7e50217 237 exit_funnel_section();
9bccf70c
A
238
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);
242 }
243
244 thread_exception_return();
245 /* NOTREACHED */
246}
247
248/*
249 * Time of day and interval timer support.
250 *
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.
256 */
257struct gettimeofday_args{
258 struct timeval *tp;
259 struct timezone *tzp;
260};
d7e50217
A
261/* NOTE THIS implementation is for ppc architectures only.
262 * It is infrequently called, since the commpage intercepts
263 * most calls in user mode.
264 */
9bccf70c
A
265int
266ppc_gettimeofday(p, uap, retval)
267 struct proc *p;
268 register struct gettimeofday_args *uap;
269 register_t *retval;
270{
9bccf70c 271 int error = 0;
d7e50217
A
272
273 if (uap->tp)
274 clock_gettimeofday(&retval[0], &retval[1]);
1c79356b 275
9bccf70c 276 if (uap->tzp) {
d7e50217
A
277 struct timezone ltz;
278 extern simple_lock_data_t tz_slock;
279
280 usimple_lock(&tz_slock);
9bccf70c
A
281 ltz = tz;
282 usimple_unlock(&tz_slock);
d7e50217 283 error = copyout((caddr_t)&ltz, (caddr_t)uap->tzp, sizeof (tz));
9bccf70c
A
284 }
285
286 return(error);
1c79356b
A
287}
288