]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/ppc/systemcalls.c
xnu-517.12.7.tar.gz
[apple/xnu.git] / bsd / dev / ppc / systemcalls.c
CommitLineData
1c79356b 1/*
55e303ae 2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
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 *
e5568f75
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,
e5568f75
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>
55e303ae 27#include <kern/clock.h>
9bccf70c
A
28#include <mach/machine/thread_status.h>
29#include <ppc/savearea.h>
30
31#include <sys/kernel.h>
32#include <sys/vm.h>
33#include <sys/proc.h>
34#include <sys/syscall.h>
35#include <sys/systm.h>
36#include <sys/user.h>
37#include <sys/errno.h>
38#include <sys/ktrace.h>
39#include <sys/kdebug.h>
e5568f75
A
40
41#include <bsm/audit_kernel.h>
9bccf70c
A
42
43extern void
44unix_syscall(
45 struct savearea *regs
46);
47
48extern struct savearea *
49find_user_regs(
50 thread_act_t act);
51
55e303ae
A
52extern void enter_funnel_section(funnel_t *funnel_lock);
53extern void exit_funnel_section(void);
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
55e303ae
A
76 flavor = (((unsigned int)regs->save_r0) == NULL)? 1: 0;
77
78 if (flavor)
79 code = regs->save_r3;
80 else
81 code = regs->save_r0;
82
83 if (kdebug_enable && (code != 180)) {
84 if (flavor)
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);
87 else
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);
90 }
9bccf70c
A
91 thread_act = current_act();
92 uthread = get_bsdthread_info(thread_act);
1c79356b 93
9bccf70c
A
94 if (!(uthread->uu_flag & P_VFORK))
95 proc = (struct proc *)get_bsdtask_info(current_task());
96 else
97 proc = current_proc();
1c79356b 98
9bccf70c 99 uthread->uu_ar0 = (int *)regs;
1c79356b 100
9bccf70c 101 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
1c79356b 102
9bccf70c
A
103#ifdef DEBUG
104 if (callp->sy_narg > 8)
105 panic("unix_syscall: max arg count exceeded");
106#endif
107
108 if (callp->sy_narg != 0) {
109 if ( !flavor) {
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;
118 } else {
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;
126 }
127 }
1c79356b 128
9bccf70c 129 funnel_type = (int)callp->sy_funnel;
55e303ae 130 if (funnel_type == KERNEL_FUNNEL)
9bccf70c
A
131 enter_funnel_section(kernel_flock);
132 else if (funnel_type == NETWORK_FUNNEL)
133 enter_funnel_section(network_flock);
134
9bccf70c 135 uthread->uu_rval[0] = 0;
1c79356b 136
1c79356b 137 /*
9bccf70c
A
138 * r4 is volatile, if we set it to regs->save_r4 here the child
139 * will have parents r4 after execve
140 */
141 uthread->uu_rval[1] = 0;
1c79356b 142
9bccf70c 143 error = 0;
1c79356b 144
9bccf70c
A
145 /*
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.
149 */
150 regs->save_srr0 += 4;
1c79356b 151
9bccf70c
A
152 if (KTRPOINT(proc, KTR_SYSCALL))
153 ktrsyscall(proc, code, callp->sy_narg, uthread->uu_arg, funnel_type);
1c79356b 154
e5568f75 155 AUDIT_SYSCALL_ENTER(code, proc, uthread);
9bccf70c 156 error = (*(callp->sy_call))(proc, (void *)uthread->uu_arg, &(uthread->uu_rval[0]));
e5568f75 157 AUDIT_SYSCALL_EXIT(error, proc, uthread);
9bccf70c
A
158
159 regs = find_user_regs(thread_act);
1c79356b 160
9bccf70c
A
161 if (error == ERESTART) {
162 regs->save_srr0 -= 8;
163 } else if (error != EJUSTRETURN) {
164 if (error) {
55e303ae 165 regs->save_r3 = (long long)error;
9bccf70c
A
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];
171 }
172 }
173 /* else (error == EJUSTRETURN) { nothing } */
1c79356b 174
9bccf70c
A
175 if (KTRPOINT(proc, KTR_SYSRET))
176 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
1c79356b 177
55e303ae 178 exit_funnel_section();
9bccf70c
A
179
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);
183 }
184
185 thread_exception_return();
186 /* NOTREACHED */
187}
188
189unix_syscall_return(error)
190{
191 thread_act_t thread_act;
192 struct uthread *uthread;
193 struct proc *proc;
194 struct savearea *regs;
195 unsigned short code;
196 struct sysent *callp;
197 int funnel_type;
198
199 thread_act = current_act();
200 proc = current_proc();
201 uthread = get_bsdthread_info(thread_act);
202
203 regs = find_user_regs(thread_act);
1c79356b
A
204
205 /*
9bccf70c
A
206 * Get index into sysent table
207 */
208 if (error == ERESTART) {
209 regs->save_srr0 -= 8;
210 } else if (error != EJUSTRETURN) {
211 if (error) {
55e303ae 212 regs->save_r3 = (long long)error;
9bccf70c
A
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];
218 }
219 }
220 /* else (error == EJUSTRETURN) { nothing } */
221
222 if (regs->save_r0 != NULL)
223 code = regs->save_r0;
224 else
225 code = regs->save_r3;
226
227 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
228
229 funnel_type = (int)callp->sy_funnel;
230
231 if (KTRPOINT(proc, KTR_SYSRET))
232 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
233
55e303ae 234 exit_funnel_section();
9bccf70c
A
235
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);
239 }
240
241 thread_exception_return();
242 /* NOTREACHED */
243}
244
245/*
246 * Time of day and interval timer support.
247 *
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.
253 */
254struct gettimeofday_args{
255 struct timeval *tp;
256 struct timezone *tzp;
257};
55e303ae
A
258/* NOTE THIS implementation is for ppc architectures only.
259 * It is infrequently called, since the commpage intercepts
260 * most calls in user mode.
261 */
9bccf70c
A
262int
263ppc_gettimeofday(p, uap, retval)
264 struct proc *p;
265 register struct gettimeofday_args *uap;
266 register_t *retval;
267{
9bccf70c 268 int error = 0;
55e303ae
A
269
270 if (uap->tp)
271 clock_gettimeofday(&retval[0], &retval[1]);
1c79356b 272
9bccf70c 273 if (uap->tzp) {
55e303ae
A
274 struct timezone ltz;
275 extern simple_lock_data_t tz_slock;
276
de355530 277 usimple_lock(&tz_slock);
9bccf70c
A
278 ltz = tz;
279 usimple_unlock(&tz_slock);
55e303ae 280 error = copyout((caddr_t)&ltz, (caddr_t)uap->tzp, sizeof (tz));
9bccf70c
A
281 }
282
55e303ae 283 return (error);
1c79356b
A
284}
285