]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/ppc/systemcalls.c
xnu-344.23.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 *
de355530
A
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.
1c79356b 11 *
de355530
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
9bccf70c
A
22
23#include <kern/task.h>
24#include <kern/thread.h>
25#include <kern/thread_act.h>
26#include <kern/assert.h>
27#include <mach/machine/thread_status.h>
28#include <ppc/savearea.h>
29
30#include <sys/kernel.h>
31#include <sys/vm.h>
32#include <sys/proc.h>
33#include <sys/syscall.h>
34#include <sys/systm.h>
35#include <sys/user.h>
36#include <sys/errno.h>
37#include <sys/ktrace.h>
38#include <sys/kdebug.h>
39
40extern void
41unix_syscall(
42 struct savearea *regs
43);
44
45extern struct savearea *
46find_user_regs(
47 thread_act_t act);
48
de355530
A
49extern enter_funnel_section(funnel_t *funnel_lock);
50extern exit_funnel_section(funnel_t *funnel_lock);
9bccf70c 51
1c79356b 52/*
9bccf70c 53 * Function: unix_syscall
1c79356b 54 *
9bccf70c 55 * Inputs: regs - pointer to Process Control Block
1c79356b 56 *
9bccf70c 57 * Outputs: none
1c79356b 58 */
9bccf70c
A
59void
60unix_syscall(
61 struct savearea *regs
62)
63{
64 thread_act_t thread_act;
65 struct uthread *uthread;
66 struct proc *proc;
67 struct sysent *callp;
68 int error;
69 unsigned short code;
70 boolean_t flavor;
71 int funnel_type;
1c79356b 72
9bccf70c
A
73 thread_act = current_act();
74 uthread = get_bsdthread_info(thread_act);
1c79356b 75
9bccf70c
A
76 if (!(uthread->uu_flag & P_VFORK))
77 proc = (struct proc *)get_bsdtask_info(current_task());
78 else
79 proc = current_proc();
1c79356b 80
de355530 81 flavor = (regs->save_r0 == NULL)? 1: 0;
1c79356b 82
9bccf70c 83 uthread->uu_ar0 = (int *)regs;
1c79356b 84
9bccf70c
A
85 if (flavor)
86 code = regs->save_r3;
87 else
88 code = regs->save_r0;
1c79356b 89
9bccf70c 90 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 91
9bccf70c
A
92#ifdef DEBUG
93 if (callp->sy_narg > 8)
94 panic("unix_syscall: max arg count exceeded");
95#endif
96
97 if (callp->sy_narg != 0) {
98 if ( !flavor) {
99 uthread->uu_arg[0] = regs->save_r3;
100 uthread->uu_arg[1] = regs->save_r4;
101 uthread->uu_arg[2] = regs->save_r5;
102 uthread->uu_arg[3] = regs->save_r6;
103 uthread->uu_arg[4] = regs->save_r7;
104 uthread->uu_arg[5] = regs->save_r8;
105 uthread->uu_arg[6] = regs->save_r9;
106 uthread->uu_arg[7] = regs->save_r10;
107 } else {
108 uthread->uu_arg[0] = regs->save_r4;
109 uthread->uu_arg[1] = regs->save_r5;
110 uthread->uu_arg[2] = regs->save_r6;
111 uthread->uu_arg[3] = regs->save_r7;
112 uthread->uu_arg[4] = regs->save_r8;
113 uthread->uu_arg[5] = regs->save_r9;
114 uthread->uu_arg[7] = regs->save_r10;
115 }
116 }
1c79356b 117
9bccf70c 118 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 119
9bccf70c
A
120 if (kdebug_enable && (code != 180)) {
121 if (flavor)
122 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
123 regs->save_r4, regs->save_r5, regs->save_r6, regs->save_r7, 0);
124 else
125 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
126 regs->save_r3, regs->save_r4, regs->save_r5, regs->save_r6, 0);
127 }
1c79356b 128
9bccf70c
A
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);
134
1c79356b 135
9bccf70c 136 uthread->uu_rval[0] = 0;
1c79356b 137
1c79356b 138 /*
9bccf70c
A
139 * r4 is volatile, if we set it to regs->save_r4 here the child
140 * will have parents r4 after execve
141 */
142 uthread->uu_rval[1] = 0;
1c79356b 143
9bccf70c 144 error = 0;
1c79356b 145
9bccf70c
A
146 /*
147 * PPC runtime calls cerror after every unix system call, so
148 * assume no error and adjust the "pc" to skip this call.
149 * It will be set back to the cerror call if an error is detected.
150 */
151 regs->save_srr0 += 4;
1c79356b 152
9bccf70c
A
153 if (KTRPOINT(proc, KTR_SYSCALL))
154 ktrsyscall(proc, code, callp->sy_narg, uthread->uu_arg, funnel_type);
1c79356b 155
9bccf70c
A
156 error = (*(callp->sy_call))(proc, (void *)uthread->uu_arg, &(uthread->uu_rval[0]));
157
158 regs = find_user_regs(thread_act);
1c79356b 159
9bccf70c
A
160 if (error == ERESTART) {
161 regs->save_srr0 -= 8;
162 } else if (error != EJUSTRETURN) {
163 if (error) {
de355530 164 regs->save_r3 = error;
9bccf70c
A
165 /* set the "pc" to execute cerror routine */
166 regs->save_srr0 -= 4;
167 } else { /* (not error) */
168 regs->save_r3 = uthread->uu_rval[0];
169 regs->save_r4 = uthread->uu_rval[1];
170 }
171 }
172 /* else (error == EJUSTRETURN) { nothing } */
1c79356b 173
9bccf70c
A
174 if (KTRPOINT(proc, KTR_SYSRET))
175 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
1c79356b 176
de355530
A
177 if(funnel_type == KERNEL_FUNNEL)
178 exit_funnel_section(kernel_flock);
179 else if (funnel_type == NETWORK_FUNNEL)
180 exit_funnel_section(network_flock);
9bccf70c
A
181
182 if (kdebug_enable && (code != 180)) {
183 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
184 error, uthread->uu_rval[0], uthread->uu_rval[1], 0, 0);
185 }
186
187 thread_exception_return();
188 /* NOTREACHED */
189}
190
191unix_syscall_return(error)
192{
193 thread_act_t thread_act;
194 struct uthread *uthread;
195 struct proc *proc;
196 struct savearea *regs;
197 unsigned short code;
198 struct sysent *callp;
199 int funnel_type;
200
201 thread_act = current_act();
202 proc = current_proc();
203 uthread = get_bsdthread_info(thread_act);
204
205 regs = find_user_regs(thread_act);
1c79356b
A
206
207 /*
9bccf70c
A
208 * Get index into sysent table
209 */
210 if (error == ERESTART) {
211 regs->save_srr0 -= 8;
212 } else if (error != EJUSTRETURN) {
213 if (error) {
de355530 214 regs->save_r3 = error;
9bccf70c
A
215 /* set the "pc" to execute cerror routine */
216 regs->save_srr0 -= 4;
217 } else { /* (not error) */
218 regs->save_r3 = uthread->uu_rval[0];
219 regs->save_r4 = uthread->uu_rval[1];
220 }
221 }
222 /* else (error == EJUSTRETURN) { nothing } */
223
224 if (regs->save_r0 != NULL)
225 code = regs->save_r0;
226 else
227 code = regs->save_r3;
228
229 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
230
231 funnel_type = (int)callp->sy_funnel;
232
233 if (KTRPOINT(proc, KTR_SYSRET))
234 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
235
de355530
A
236 if(funnel_type == KERNEL_FUNNEL)
237 exit_funnel_section(kernel_flock);
238 else if (funnel_type == NETWORK_FUNNEL)
239 exit_funnel_section(network_flock);
9bccf70c
A
240
241 if (kdebug_enable && (code != 180)) {
242 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
243 error, uthread->uu_rval[0], uthread->uu_rval[1], 0, 0);
244 }
245
246 thread_exception_return();
247 /* NOTREACHED */
248}
249
250/*
251 * Time of day and interval timer support.
252 *
253 * These routines provide the kernel entry points to get and set
254 * the time-of-day and per-process interval timers. Subroutines
255 * here provide support for adding and subtracting timeval structures
256 * and decrementing interval timers, optionally reloading the interval
257 * timers when they expire.
258 */
259struct gettimeofday_args{
260 struct timeval *tp;
261 struct timezone *tzp;
262};
de355530 263/* NOTE THIS implementation is for ppc architectures only */
9bccf70c
A
264int
265ppc_gettimeofday(p, uap, retval)
266 struct proc *p;
267 register struct gettimeofday_args *uap;
268 register_t *retval;
269{
de355530 270 struct timeval atv;
9bccf70c 271 int error = 0;
de355530
A
272 struct timezone ltz;
273 //struct savearea *child_state;
274 extern simple_lock_data_t tz_slock;
275
276 if (uap->tp) {
277 microtime(&atv);
278 retval[0] = atv.tv_sec;
279 retval[1] = atv.tv_usec;
280 }
1c79356b 281
9bccf70c 282 if (uap->tzp) {
de355530 283 usimple_lock(&tz_slock);
9bccf70c
A
284 ltz = tz;
285 usimple_unlock(&tz_slock);
de355530
A
286 error = copyout((caddr_t)&ltz, (caddr_t)uap->tzp,
287 sizeof (tz));
9bccf70c
A
288 }
289
290 return(error);
1c79356b
A
291}
292