1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 #include <kern/task.h>
27 #include <kern/thread.h>
28 #include <kern/thread_act.h>
29 #include <kern/assert.h>
30 #include <kern/clock.h>
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 #include <sys/kern_audit.h>
44
45 extern void
46 unix_syscall(
47 struct savearea *regs
48 );
49
50 extern struct savearea *
51 find_user_regs(
52 thread_act_t act);
53
54 extern void enter_funnel_section(funnel_t *funnel_lock);
55 extern void exit_funnel_section(void);
56
57 /*
58 * Function: unix_syscall
59 *
60 * Inputs: regs - pointer to Process Control Block
61 *
62 * Outputs: none
63 */
64 void
65 unix_syscall(
66 struct savearea *regs
67 )
68 {
69 thread_act_t thread_act;
70 struct uthread *uthread;
71 struct proc *proc;
72 struct sysent *callp;
73 int error;
74 unsigned short code;
75 boolean_t flavor;
76 int funnel_type;
77
78 flavor = (((unsigned int)regs->save_r0) == NULL)? 1: 0;
79
80 if (flavor)
81 code = regs->save_r3;
82 else
83 code = regs->save_r0;
84
85 if (kdebug_enable && (code != 180)) {
86 if (flavor)
87 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
88 regs->save_r4, regs->save_r5, regs->save_r6, regs->save_r7, 0);
89 else
90 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
91 regs->save_r3, regs->save_r4, regs->save_r5, regs->save_r6, 0);
92 }
93 thread_act = current_act();
94 uthread = get_bsdthread_info(thread_act);
95
96 if (!(uthread->uu_flag & P_VFORK))
97 proc = (struct proc *)get_bsdtask_info(current_task());
98 else
99 proc = current_proc();
100
101 uthread->uu_ar0 = (int *)regs;
102
103 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
104
105 #ifdef DEBUG
106 if (callp->sy_narg > 8)
107 panic("unix_syscall: max arg count exceeded");
108 #endif
109
110 if (callp->sy_narg != 0) {
111 if ( !flavor) {
112 uthread->uu_arg[0] = regs->save_r3;
113 uthread->uu_arg[1] = regs->save_r4;
114 uthread->uu_arg[2] = regs->save_r5;
115 uthread->uu_arg[3] = regs->save_r6;
116 uthread->uu_arg[4] = regs->save_r7;
117 uthread->uu_arg[5] = regs->save_r8;
118 uthread->uu_arg[6] = regs->save_r9;
119 uthread->uu_arg[7] = regs->save_r10;
120 } else {
121 uthread->uu_arg[0] = regs->save_r4;
122 uthread->uu_arg[1] = regs->save_r5;
123 uthread->uu_arg[2] = regs->save_r6;
124 uthread->uu_arg[3] = regs->save_r7;
125 uthread->uu_arg[4] = regs->save_r8;
126 uthread->uu_arg[5] = regs->save_r9;
127 uthread->uu_arg[7] = regs->save_r10;
128 }
129 }
130
131 funnel_type = (int)callp->sy_funnel;
132 if (funnel_type == KERNEL_FUNNEL)
133 enter_funnel_section(kernel_flock);
134 else if (funnel_type == NETWORK_FUNNEL)
135 enter_funnel_section(network_flock);
136
137 uthread->uu_rval[0] = 0;
138
139 /*
140 * r4 is volatile, if we set it to regs->save_r4 here the child
141 * will have parents r4 after execve
142 */
143 uthread->uu_rval[1] = 0;
144
145 error = 0;
146
147 /*
148 * PPC runtime calls cerror after every unix system call, so
149 * assume no error and adjust the "pc" to skip this call.
150 * It will be set back to the cerror call if an error is detected.
151 */
152 regs->save_srr0 += 4;
153
154 if (KTRPOINT(proc, KTR_SYSCALL))
155 ktrsyscall(proc, code, callp->sy_narg, uthread->uu_arg, funnel_type);
156
157 AUDIT_CMD(audit_syscall_enter(code, proc, uthread));
158 error = (*(callp->sy_call))(proc, (void *)uthread->uu_arg, &(uthread->uu_rval[0]));
159 AUDIT_CMD(audit_syscall_exit(error, proc, uthread));
160
161 regs = find_user_regs(thread_act);
162
163 if (error == ERESTART) {
164 regs->save_srr0 -= 8;
165 } else if (error != EJUSTRETURN) {
166 if (error) {
167 regs->save_r3 = (long long)error;
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 } */
176
177 if (KTRPOINT(proc, KTR_SYSRET))
178 ktrsysret(proc, code, error, uthread->uu_rval[0], funnel_type);
179
180 exit_funnel_section();
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
191 unix_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);
206
207 /*
208 * Get index into sysent table
209 */
210 if (error == ERESTART) {
211 regs->save_srr0 -= 8;
212 } else if (error != EJUSTRETURN) {
213 if (error) {
214 regs->save_r3 = (long long)error;
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
236 exit_funnel_section();
237
238 if (kdebug_enable && (code != 180)) {
239 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
240 error, uthread->uu_rval[0], uthread->uu_rval[1], 0, 0);
241 }
242
243 thread_exception_return();
244 /* NOTREACHED */
245 }
246
247 /*
248 * Time of day and interval timer support.
249 *
250 * These routines provide the kernel entry points to get and set
251 * the time-of-day and per-process interval timers. Subroutines
252 * here provide support for adding and subtracting timeval structures
253 * and decrementing interval timers, optionally reloading the interval
254 * timers when they expire.
255 */
256 struct gettimeofday_args{
257 struct timeval *tp;
258 struct timezone *tzp;
259 };
260 /* NOTE THIS implementation is for ppc architectures only.
261 * It is infrequently called, since the commpage intercepts
262 * most calls in user mode.
263 */
264 int
265 ppc_gettimeofday(p, uap, retval)
266 struct proc *p;
267 register struct gettimeofday_args *uap;
268 register_t *retval;
269 {
270 int error = 0;
271
272 if (uap->tp)
273 clock_gettimeofday(&retval[0], &retval[1]);
274
275 if (uap->tzp) {
276 struct timezone ltz;
277 extern simple_lock_data_t tz_slock;
278
279 usimple_lock(&tz_slock);
280 ltz = tz;
281 usimple_unlock(&tz_slock);
282 error = copyout((caddr_t)<z, (caddr_t)uap->tzp, sizeof (tz));
283 }
284
285 return (error);
286 }
287
Cache object: b46aaee262f2076f4458e39fe8b4ada6
|