]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/ppc/systemcalls.c
xnu-344.49.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 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
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,
43866e37
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>
30#include <mach/machine/thread_status.h>
31#include <ppc/savearea.h>
32
33#include <sys/kernel.h>
34#include <sys/vm.h>
35#include <sys/proc.h>
36#include <sys/syscall.h>
37#include <sys/systm.h>
38#include <sys/user.h>
39#include <sys/errno.h>
40#include <sys/ktrace.h>
41#include <sys/kdebug.h>
42
43extern void
44unix_syscall(
45 struct savearea *regs
46);
47
48extern struct savearea *
49find_user_regs(
50 thread_act_t act);
51
de355530
A
52extern enter_funnel_section(funnel_t *funnel_lock);
53extern exit_funnel_section(funnel_t *funnel_lock);
9bccf70c 54
1c79356b 55/*
9bccf70c 56 * Function: unix_syscall
1c79356b 57 *
9bccf70c 58 * Inputs: regs - pointer to Process Control Block
1c79356b 59 *
9bccf70c 60 * Outputs: none
1c79356b 61 */
9bccf70c
A
62void
63unix_syscall(
64 struct savearea *regs
65)
66{
67 thread_act_t thread_act;
68 struct uthread *uthread;
69 struct proc *proc;
70 struct sysent *callp;
71 int error;
72 unsigned short code;
73 boolean_t flavor;
74 int funnel_type;
1c79356b 75
9bccf70c
A
76 thread_act = current_act();
77 uthread = get_bsdthread_info(thread_act);
1c79356b 78
9bccf70c
A
79 if (!(uthread->uu_flag & P_VFORK))
80 proc = (struct proc *)get_bsdtask_info(current_task());
81 else
82 proc = current_proc();
1c79356b 83
de355530 84 flavor = (regs->save_r0 == NULL)? 1: 0;
1c79356b 85
9bccf70c 86 uthread->uu_ar0 = (int *)regs;
1c79356b 87
9bccf70c
A
88 if (flavor)
89 code = regs->save_r3;
90 else
91 code = regs->save_r0;
1c79356b 92
9bccf70c 93 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 94
9bccf70c
A
95#ifdef DEBUG
96 if (callp->sy_narg > 8)
97 panic("unix_syscall: max arg count exceeded");
98#endif
99
100 if (callp->sy_narg != 0) {
101 if ( !flavor) {
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;
110 } else {
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;
118 }
119 }
1c79356b 120
9bccf70c 121 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 122
9bccf70c
A
123 if (kdebug_enable && (code != 180)) {
124 if (flavor)
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);
127 else
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);
130 }
1c79356b 131
9bccf70c
A
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);
137
1c79356b 138
9bccf70c 139 uthread->uu_rval[0] = 0;
1c79356b 140
1c79356b 141 /*
9bccf70c
A
142 * r4 is volatile, if we set it to regs->save_r4 here the child
143 * will have parents r4 after execve
144 */
145 uthread->uu_rval[1] = 0;
1c79356b 146
9bccf70c 147 error = 0;
1c79356b 148
9bccf70c
A
149 /*
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.
153 */
154 regs->save_srr0 += 4;
1c79356b 155
9bccf70c
A
156 if (KTRPOINT(proc, KTR_SYSCALL))
157 ktrsyscall(proc, code, callp->sy_narg, uthread->uu_arg, funnel_type);
1c79356b 158
9bccf70c
A
159 error = (*(callp->sy_call))(proc, (void *)uthread->uu_arg, &(uthread->uu_rval[0]));
160
161 regs = find_user_regs(thread_act);
1c79356b 162
9bccf70c
A
163 if (error == ERESTART) {
164 regs->save_srr0 -= 8;
165 } else if (error != EJUSTRETURN) {
166 if (error) {
de355530 167 regs->save_r3 = error;
9bccf70c
A
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];
173 }
174 }
175 /* else (error == EJUSTRETURN) { nothing } */
1c79356b 176
9bccf70c
A
177 if (KTRPOINT(proc, KTR_SYSRET))
178 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
1c79356b 179
de355530
A
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);
9bccf70c
A
184
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);
188 }
189
190 thread_exception_return();
191 /* NOTREACHED */
192}
193
194unix_syscall_return(error)
195{
196 thread_act_t thread_act;
197 struct uthread *uthread;
198 struct proc *proc;
199 struct savearea *regs;
200 unsigned short code;
201 struct sysent *callp;
202 int funnel_type;
203
204 thread_act = current_act();
205 proc = current_proc();
206 uthread = get_bsdthread_info(thread_act);
207
208 regs = find_user_regs(thread_act);
1c79356b
A
209
210 /*
9bccf70c
A
211 * Get index into sysent table
212 */
213 if (error == ERESTART) {
214 regs->save_srr0 -= 8;
215 } else if (error != EJUSTRETURN) {
216 if (error) {
de355530 217 regs->save_r3 = error;
9bccf70c
A
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];
223 }
224 }
225 /* else (error == EJUSTRETURN) { nothing } */
226
227 if (regs->save_r0 != NULL)
228 code = regs->save_r0;
229 else
230 code = regs->save_r3;
231
232 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
233
234 funnel_type = (int)callp->sy_funnel;
235
236 if (KTRPOINT(proc, KTR_SYSRET))
237 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
238
de355530
A
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);
9bccf70c
A
243
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);
247 }
248
249 thread_exception_return();
250 /* NOTREACHED */
251}
252
253/*
254 * Time of day and interval timer support.
255 *
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.
261 */
262struct gettimeofday_args{
263 struct timeval *tp;
264 struct timezone *tzp;
265};
de355530 266/* NOTE THIS implementation is for ppc architectures only */
9bccf70c
A
267int
268ppc_gettimeofday(p, uap, retval)
269 struct proc *p;
270 register struct gettimeofday_args *uap;
271 register_t *retval;
272{
de355530 273 struct timeval atv;
9bccf70c 274 int error = 0;
de355530
A
275 struct timezone ltz;
276 //struct savearea *child_state;
277 extern simple_lock_data_t tz_slock;
278
279 if (uap->tp) {
280 microtime(&atv);
281 retval[0] = atv.tv_sec;
282 retval[1] = atv.tv_usec;
283 }
1c79356b 284
9bccf70c 285 if (uap->tzp) {
de355530 286 usimple_lock(&tz_slock);
9bccf70c
A
287 ltz = tz;
288 usimple_unlock(&tz_slock);
de355530
A
289 error = copyout((caddr_t)&ltz, (caddr_t)uap->tzp,
290 sizeof (tz));
9bccf70c
A
291 }
292
293 return(error);
1c79356b
A
294}
295