]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/bsd_ppc.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / ppc / bsd_ppc.c
CommitLineData
de355530
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
de355530 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
de355530
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.
de355530
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#include <mach/mach_types.h>
26#include <mach/exception_types.h>
27#include <mach/error.h>
28#include <kern/counters.h>
29#include <kern/syscall_sw.h>
30#include <kern/task.h>
31#include <kern/thread.h>
32#include <ppc/thread.h>
33#include <kern/thread_act.h>
34#include <ppc/thread_act.h>
35#include <ppc/asm.h>
36#include <ppc/proc_reg.h>
37#include <ppc/trap.h>
38#include <ppc/exception.h>
39#include <kern/assert.h>
40
41#include <sys/syscall.h>
42#include <sys/ktrace.h>
43#include <sys/kdebug.h>
44struct proc;
45
46#define ERESTART -1 /* restart syscall */
47#define EJUSTRETURN -2 /* don't modify regs, just return */
48
49struct unix_syscallargs {
50 int flavor;
51 int r3;
52 int arg1, arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9;
53};
54struct sysent { /* system call table */
55 unsigned short sy_narg; /* number of args */
56 char sy_parallel; /* can execute in parallel */
57 char sy_funnel; /* funnel type */
58 unsigned long (*sy_call)(void *, void *, int *); /* implementing function */
59};
60
61#define KERNEL_FUNNEL 1
62#define NETWORK_FUNNEL 2
63
64extern funnel_t * kernel_flock;
65extern funnel_t * network_flock;
66
67extern struct sysent sysent[];
68
69void *get_bsdtask_info(
70 task_t);
71
72int set_bsduthreadargs (
73 thread_act_t, struct pcb *,
74 struct unix_syscallargs *);
75
76void * get_bsduthreadarg(
77 thread_act_t);
78
79void
80unix_syscall(
81 struct pcb * pcb,
82 int, int, int, int, int, int, int );
83
84/*
85 * Function: unix_syscall
86 *
87 * Inputs: pcb - pointer to Process Control Block
88 * arg1 - arguments to mach system calls
89 * arg2
90 * arg3
91 * arg4
92 * arg5
93 * arg6
94 * arg7
95 *
96 * Outputs: none
97 */
98void
99unix_syscall(
100 struct pcb * pcb,
101 int arg1,
102 int arg2,
103 int arg3,
104 int arg4,
105 int arg5,
106 int arg6,
107 int arg7
108 )
109{
110 struct ppc_saved_state *regs;
111 thread_act_t thread;
112 struct sysent *callp;
113 int nargs, error;
114 unsigned short code;
115 struct proc *p;
116 void *vt;
117 int * vtint;
118 int *rval;
119 int funnel_type;
120 struct proc *current_proc();
121
122 struct unix_syscallargs sarg;
123 extern int nsysent;
124
125 regs = &pcb->ss;
126 code = regs->r0;
127
128 thread = current_act();
129 p = current_proc();
130 rval = (int *)get_bsduthreadrval(thread);
131
132 /*
133 * Set up call pointer
134 */
135 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
136
137 sarg. flavor = (callp == sysent)? 1: 0;
138 if (sarg.flavor) {
139 code = regs->r3;
140 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
141 } else
142 sarg. r3 = regs->r3;
143
144 if (code != 180) {
145 if (sarg.flavor)
146 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
147 arg1, arg2, arg3, arg4, 0);
148 else
149 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
150 sarg.r3, arg1, arg2, arg3, 0);
151 }
152 sarg.arg1 = arg1;
153 sarg.arg2 = arg2;
154 sarg.arg3 = arg3;
155 sarg.arg4 = arg4;
156 sarg.arg5 = arg5;
157 sarg.arg6 = arg6;
158 sarg.arg7 = arg7;
159
160 if(callp->sy_funnel == NETWORK_FUNNEL) {
161 (void) thread_funnel_set(network_flock, TRUE);
162 } else {
163 (void) thread_funnel_set(kernel_flock, TRUE);
164 }
165
166 set_bsduthreadargs(thread,pcb,&sarg);
167
168 if (callp->sy_narg > 8)
169 panic("unix_syscall: max arg count exceeded");
170
171 rval[0] = 0;
172
173 /*
174 * r4 is volatile, if we set it to regs->r4 here the child
175 * will have parents r4 after execve
176 */
177 rval[1] = 0;
178
179 error = 0; /* Start with a good value */
180
181 /*
182 ** the PPC runtime calls cerror after every unix system call, so
183 ** assume no error and adjust the "pc" to skip this call.
184 ** It will be set back to the cerror call if an error is detected.
185 */
186 regs->srr0 += 4;
187 vt = get_bsduthreadarg(thread);
188 counter_always(c_syscalls_unix++);
189 current_task()->syscalls_unix++;
190
191 ktrsyscall(p, code, callp->sy_narg, vt);
192
193 error = (*(callp->sy_call))(p, (void *)vt, rval);
194
195 regs = find_user_regs(thread);
196 if (regs == (struct ppc_saved_state *)0)
197 panic("No user savearea while returning from system call");
198
199 if (error == ERESTART) {
200 regs->srr0 -= 8;
201 } else if (error != EJUSTRETURN) {
202 if (error) {
203 regs->r3 = error;
204 /* set the "pc" to execute cerror routine */
205 regs->srr0 -= 4;
206 } else { /* (not error) */
207 regs->r3 = rval[0];
208 regs->r4 = rval[1];
209 }
210 }
211 /* else (error == EJUSTRETURN) { nothing } */
212
213 ktrsysret(p, code, error, rval[0]);
214
215 (void) thread_funnel_set(current_thread()->funnel_lock, FALSE);
216
217 if (code != 180) {
218 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
219 error, rval[0], rval[1], 0, 0);
220 }
221
222 thread_exception_return();
223 /* NOTREACHED */
224}
225
226unix_syscall_return(error)
227{
228 struct ppc_saved_state *regs;
229 thread_act_t thread;
230 struct sysent *callp;
231 int nargs;
232 unsigned short code;
233 int *rval;
234 struct proc *p;
235 void *vt;
236 int * vtint;
237 struct pcb *pcb;
238 struct proc *current_proc();
239
240 struct unix_syscallargs sarg;
241 extern int nsysent;
242
243 thread = current_act();
244 p = current_proc();
245 rval = (int *)get_bsduthreadrval(thread);
246 pcb = thread->mact.pcb;
247 regs = &pcb->ss;
248
249 if (thread_funnel_get() == THR_FUNNEL_NULL)
250 panic("Unix syscall return without funnel held");
251
252 /*
253 * Get index into sysent table
254 */
255 code = regs->r0;
256
257 if (error == ERESTART) {
258 regs->srr0 -= 8;
259 } else if (error != EJUSTRETURN) {
260 if (error) {
261 regs->r3 = error;
262 /* set the "pc" to execute cerror routine */
263 regs->srr0 -= 4;
264 } else { /* (not error) */
265 regs->r3 = rval[0];
266 regs->r4 = rval[1];
267 }
268 }
269 /* else (error == EJUSTRETURN) { nothing } */
270
271 ktrsysret(p, code, error, rval[0]);
272
273 (void) thread_funnel_set(current_thread()->funnel_lock, FALSE);
274
275 if (code != 180) {
276 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
277 error, rval[0], rval[1], 0, 0);
278 }
279
280 thread_exception_return();
281 /* NOTREACHED */
282}
283