aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/syscalls.c
diff options
context:
space:
mode:
authorChris Zankel <czankel@tensilica.com>2006-12-10 05:18:52 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-10 12:55:39 -0500
commitfc4fb2adf944d45a7f3d4d38df991c79ffdb6a43 (patch)
treebee95910d719861e2a189f7464b6bd6de6f22d1c /arch/xtensa/kernel/syscalls.c
parent173d6681380aa1d60dfc35ed7178bd7811ba2784 (diff)
[PATCH] xtensa: fix system call interface
This is a long outstanding patch to finally fix the syscall interface. The constants used for the system calls are those we have provided in our libc patches. This patch also fixes the shmbuf and stat structure, and fcntl definitions. Signed-off-by: Chris Zankel <chris@zankel.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/xtensa/kernel/syscalls.c')
-rw-r--r--arch/xtensa/kernel/syscalls.c288
1 files changed, 0 insertions, 288 deletions
diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c
deleted file mode 100644
index f9a5a752ca69..000000000000
--- a/arch/xtensa/kernel/syscalls.c
+++ /dev/null
@@ -1,288 +0,0 @@
1/*
2 * arch/xtensa/kernel/syscalls.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 * Copyright (C) 2000 Silicon Graphics, Inc.
10 * Copyright (C) 1995 - 2000 by Ralf Baechle
11 *
12 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
14 * Chris Zankel <chris@zankel.net>
15 * Kevin Chea
16 *
17 */
18
19#define DEBUG 0
20
21#include <linux/linkage.h>
22#include <linux/mm.h>
23#include <linux/smp.h>
24#include <linux/smp_lock.h>
25#include <linux/mman.h>
26#include <linux/sched.h>
27#include <linux/file.h>
28#include <linux/slab.h>
29#include <linux/utsname.h>
30#include <linux/unistd.h>
31#include <linux/stringify.h>
32#include <linux/syscalls.h>
33#include <linux/sem.h>
34#include <linux/msg.h>
35#include <linux/shm.h>
36#include <linux/errno.h>
37#include <asm/ptrace.h>
38#include <asm/signal.h>
39#include <asm/uaccess.h>
40#include <asm/hardirq.h>
41#include <asm/mman.h>
42#include <asm/shmparam.h>
43#include <asm/page.h>
44
45extern void do_syscall_trace(void);
46typedef int (*syscall_t)(void *a0,...);
47extern syscall_t sys_call_table[];
48extern unsigned char sys_narg_table[];
49
50/*
51 * sys_pipe() is the normal C calling standard for creating a pipe. It's not
52 * the way unix traditional does this, though.
53 */
54
55int sys_pipe(int __user *userfds)
56{
57 int fd[2];
58 int error;
59
60 error = do_pipe(fd);
61 if (!error) {
62 if (copy_to_user(userfds, fd, 2 * sizeof(int)))
63 error = -EFAULT;
64 }
65 return error;
66}
67
68/*
69 * Common code for old and new mmaps.
70 */
71long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
72 unsigned long flags, unsigned long fd, unsigned long pgoff)
73{
74 int error = -EBADF;
75 struct file * file = NULL;
76
77 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
78 if (!(flags & MAP_ANONYMOUS)) {
79 file = fget(fd);
80 if (!file)
81 goto out;
82 }
83
84 down_write(&current->mm->mmap_sem);
85 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
86 up_write(&current->mm->mmap_sem);
87
88 if (file)
89 fput(file);
90out:
91 return error;
92}
93
94int sys_clone(struct pt_regs *regs)
95{
96 unsigned long clone_flags;
97 unsigned long newsp;
98 int __user *parent_tidptr, *child_tidptr;
99 clone_flags = regs->areg[4];
100 newsp = regs->areg[3];
101 parent_tidptr = (int __user *)regs->areg[5];
102 child_tidptr = (int __user *)regs->areg[6];
103 if (!newsp)
104 newsp = regs->areg[1];
105 return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
106}
107
108/*
109 * sys_execve() executes a new program.
110 */
111
112int sys_execve(struct pt_regs *regs)
113{
114 int error;
115 char * filename;
116
117 filename = getname((char *) (long)regs->areg[5]);
118 error = PTR_ERR(filename);
119 if (IS_ERR(filename))
120 goto out;
121 error = do_execve(filename, (char **) (long)regs->areg[3],
122 (char **) (long)regs->areg[4], regs);
123 putname(filename);
124
125out:
126 return error;
127}
128
129int sys_uname(struct old_utsname * name)
130{
131 if (name && !copy_to_user(name, utsname(), sizeof (*name)))
132 return 0;
133 return -EFAULT;
134}
135
136/*
137 * Build the string table for the builtin "poor man's strace".
138 */
139
140#if DEBUG
141#define SYSCALL(fun, narg) #fun,
142static char *sfnames[] = {
143#include "syscalls.h"
144};
145#undef SYS
146#endif
147
148void system_call (struct pt_regs *regs)
149{
150 syscall_t syscall;
151 unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
152 int nargs, res;
153 unsigned int syscallnr;
154 int ps;
155
156#if DEBUG
157 int i;
158 unsigned long parms[6];
159 char *sysname;
160#endif
161
162 regs->syscall = regs->areg[2];
163
164 do_syscall_trace();
165
166 /* Have to load after syscall_trace because strace
167 * sometimes changes regs->syscall.
168 */
169 syscallnr = regs->syscall;
170
171 parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
172
173 /* Restore interrupt level to syscall invoker's.
174 * If this were in assembly, we wouldn't disable
175 * interrupts in the first place:
176 */
177 local_save_flags (ps);
178 local_irq_restore((ps & ~PS_INTLEVEL_MASK) |
179 (regs->ps & PS_INTLEVEL_MASK) );
180
181 if (syscallnr > __NR_Linux_syscalls) {
182 regs->areg[2] = -ENOSYS;
183 return;
184 }
185
186 syscall = sys_call_table[syscallnr];
187 nargs = sys_narg_table[syscallnr];
188
189 if (syscall == NULL) {
190 regs->areg[2] = -ENOSYS;
191 return;
192 }
193
194 /* There shouldn't be more than six arguments in the table! */
195
196 if (nargs > 6)
197 panic("Internal error - too many syscall arguments (%d)!\n",
198 nargs);
199
200 /* Linux takes system-call arguments in registers. The ABI
201 * and Xtensa software conventions require the system-call
202 * number in a2. If an argument exists in a2, we move it to
203 * the next available register. Note that for improved
204 * efficiency, we do NOT shift all parameters down one
205 * register to maintain the original order.
206 *
207 * At best case (zero arguments), we just write the syscall
208 * number to a2. At worst case (1 to 6 arguments), we move
209 * the argument in a2 to the next available register, then
210 * write the syscall number to a2.
211 *
212 * For clarity, the following truth table enumerates all
213 * possibilities.
214 *
215 * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5
216 * --------- -------------- ----------------------------------
217 * 0 a2
218 * 1 a2 a3
219 * 2 a2 a4, a3
220 * 3 a2 a5, a3, a4
221 * 4 a2 a6, a3, a4, a5
222 * 5 a2 a7, a3, a4, a5, a6
223 * 6 a2 a8, a3, a4, a5, a6, a7
224 */
225 if (nargs) {
226 parm0 = regs->areg[nargs+2];
227 parm1 = regs->areg[3];
228 parm2 = regs->areg[4];
229 parm3 = regs->areg[5];
230 parm4 = regs->areg[6];
231 parm5 = regs->areg[7];
232 } else /* nargs == 0 */
233 parm0 = (unsigned long) regs;
234
235#if DEBUG
236 parms[0] = parm0;
237 parms[1] = parm1;
238 parms[2] = parm2;
239 parms[3] = parm3;
240 parms[4] = parm4;
241 parms[5] = parm5;
242
243 sysname = sfnames[syscallnr];
244 if (strncmp(sysname, "sys_", 4) == 0)
245 sysname = sysname + 4;
246
247 printk("\017SYSCALL:I:%x:%d:%s %s(", regs->pc, current->pid,
248 current->comm, sysname);
249 for (i = 0; i < nargs; i++)
250 printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
251 printk(")\n");
252#endif
253
254 res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
255
256#if DEBUG
257 printk("\017SYSCALL:O:%d:%s %s(",current->pid, current->comm, sysname);
258 for (i = 0; i < nargs; i++)
259 printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
260 if (res < 4096)
261 printk(") = %d\n", res);
262 else
263 printk(") = %#x\n", res);
264#endif /* DEBUG */
265
266 regs->areg[2] = res;
267 do_syscall_trace();
268}
269
270/*
271 * Do a system call from kernel instead of calling sys_execve so we
272 * end up with proper pt_regs.
273 */
274int kernel_execve(const char *filename, char *const argv[], char *const envp[])
275{
276 long __res;
277 asm volatile (
278 " mov a5, %2 \n"
279 " mov a4, %4 \n"
280 " mov a3, %3 \n"
281 " movi a2, %1 \n"
282 " syscall \n"
283 " mov %0, a2 \n"
284 : "=a" (__res)
285 : "i" (__NR_execve), "a" (filename), "a" (argv), "a" (envp)
286 : "a2", "a3", "a4", "a5");
287 return __res;
288}