|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: #include <mach/mach_types.h>
23: #include <mach/exception_types.h>
24: #include <mach/error.h>
25: #include <kern/counters.h>
26: #include <kern/syscall_sw.h>
27: #include <kern/task.h>
28: #include <kern/thread.h>
29: #include <ppc/thread.h>
30: #include <kern/thread_act.h>
31: #include <ppc/thread_act.h>
32: #include <ppc/asm.h>
33: #include <ppc/proc_reg.h>
34: #include <ppc/trap.h>
35: #include <ppc/exception.h>
36: #include <kern/assert.h>
37:
38: #include <sys/kdebug.h>
39:
40: #define ERESTART -1 /* restart syscall */
41: #define EJUSTRETURN -2 /* don't modify regs, just return */
42:
43: struct unix_syscallargs {
44: int flavor;
45: int r3;
46: int arg1, arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9;
47: };
48: struct sysent { /* system call table */
49: unsigned short sy_narg; /* number of args */
50: unsigned short sy_parallel; /* can execute in parallel */
51: unsigned long (*sy_call)(void *, void *, int *); /* implementing function */
52: };
53:
54: extern struct sysent sysent[];
55:
56: void *get_bsdtask_info(
57: task_t);
58:
59: int set_bsduthreadargs (
60: thread_act_t, struct pcb *,
61: struct unix_syscallargs *);
62:
63: void * get_bsduthreadarg(
64: thread_act_t);
65:
66: void
67: unix_syscall(
68: struct pcb * pcb,
69: int, int, int, int, int, int, int );
70:
71: /*
72: * Function: unix_syscall
73: *
74: * Inputs: pcb - pointer to Process Control Block
75: * arg1 - arguments to mach system calls
76: * arg2
77: * arg3
78: * arg4
79: * arg5
80: * arg6
81: * arg7
82: *
83: * Outputs: none
84: */
85: void
86: unix_syscall(
87: struct pcb * pcb,
88: int arg1,
89: int arg2,
90: int arg3,
91: int arg4,
92: int arg5,
93: int arg6,
94: int arg7
95: )
96: {
97: struct ppc_saved_state *regs;
98: thread_act_t thread;
99: struct sysent *callp;
100: int nargs, error;
101: unsigned short code;
102: void * p, *vt;
103: int * vtint;
104: int *rval;
105:
106: struct unix_syscallargs sarg;
107: extern int nsysent;
108:
109: (void) thread_set_funneled(TRUE);
110:
111: regs = &pcb->ss;
112: thread = current_act();
113: p = get_bsdtask_info(current_task());
114: rval = (int *)get_bsduthreadrval(thread);
115:
116: /*
117: ** Get index into sysent table
118: */
119: code = regs->r0;
120:
121:
122: /*
123: ** Set up call pointer
124: */
125: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
126:
127: sarg. flavor = (callp == sysent)? 1: 0;
128: if (sarg.flavor) {
129: code = regs->r3;
130: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
131:
132: }
133: else
134: sarg. r3 = regs->r3;
135: sarg. arg1 = arg1;
136: sarg. arg2 = arg2;
137: sarg. arg3 = arg3;
138: sarg. arg4 = arg4;
139: sarg. arg5 = arg5;
140: sarg. arg6 = arg6;
141: sarg. arg7 = arg7;
142:
143: set_bsduthreadargs(thread,pcb,&sarg);
144:
145:
146: if (callp->sy_narg > 8)
147: panic("unix_syscall: max arg count exceeded");
148:
149: rval[0] = 0;
150:
151: /* r4 is volatile, if we set it to regs->r4 here the child
152: * will have parents r4 after execve */
153: rval[1] = 0;
154:
155: error = 0; /* Start with a good value */
156:
157: /*
158: ** the PPC runtime calls cerror after every unix system call, so
159: ** assume no error and adjust the "pc" to skip this call.
160: ** It will be set back to the cerror call if an error is detected.
161: */
162: regs->srr0 += 4;
163: vt = get_bsduthreadarg(thread);
164:
165: if (code != 180) {
166: vtint = (int *) vt;
167: KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
168: vtint[0],vtint[1], vtint[2], vtint[3], 0);
169: }
170:
171: counter_always(c_syscalls_unix++);
172: current_task()->syscalls_unix++;
173: error = (*(callp->sy_call))(p, (void *)vt, rval);
174:
175: if (code != 180) {
176: KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
177: error, rval[0], rval[1], 0, 0);
178: }
179:
180: if (error == ERESTART) {
181: regs->srr0 -= 8;
182: }
183: else if (error != EJUSTRETURN) {
184: if (error)
185: {
186: regs->r3 = error;
187: /* set the "pc" to execute cerror routine */
188: regs->srr0 -= 4;
189: } else { /* (not error) */
190: regs->r3 = rval[0];
191: regs->r4 = rval[1];
192: }
193: }
194: /* else (error == EJUSTRETURN) { nothing } */
195:
196: (void) thread_set_funneled(FALSE);
197:
198: thread_exception_return();
199: /* NOTREACHED */
200: }
201:
202: unix_syscall_return(error)
203: {
204: struct ppc_saved_state *regs;
205: thread_act_t thread;
206: struct sysent *callp;
207: int nargs;
208: unsigned short code;
209: int *rval;
210: void * p, *vt;
211: int * vtint;
212: struct pcb *pcb;
213:
214: struct unix_syscallargs sarg;
215: extern int nsysent;
216:
217: thread = current_act();
218: p = get_bsdtask_info(current_task());
219: rval = (int *)get_bsduthreadrval(thread);
220: pcb = thread->mact.pcb;
221: regs = &pcb->ss;
222:
223: /*
224: ** Get index into sysent table
225: */
226: code = regs->r0;
227:
228: if (code != 180) {
229: KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
230: error, rval[0], rval[1], 0, 0);
231: }
232:
233: if (error == ERESTART) {
234: regs->srr0 -= 8;
235: }
236: else if (error != EJUSTRETURN) {
237: if (error)
238: {
239: regs->r3 = error;
240: /* set the "pc" to execute cerror routine */
241: regs->srr0 -= 4;
242: } else { /* (not error) */
243: regs->r3 = rval[0];
244: regs->r4 = rval[1];
245: }
246: }
247: /* else (error == EJUSTRETURN) { nothing } */
248:
249: (void) thread_set_funneled(FALSE);
250:
251: thread_exception_return();
252: /* NOTREACHED */
253: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.