aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel
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
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')
-rw-r--r--arch/xtensa/kernel/asm-offsets.c5
-rw-r--r--arch/xtensa/kernel/entry.S228
-rw-r--r--arch/xtensa/kernel/process.c71
-rw-r--r--arch/xtensa/kernel/ptrace.c26
-rw-r--r--arch/xtensa/kernel/signal.c12
-rw-r--r--arch/xtensa/kernel/syscall.c95
-rw-r--r--arch/xtensa/kernel/syscalls.c288
-rw-r--r--arch/xtensa/kernel/syscalls.h247
8 files changed, 317 insertions, 655 deletions
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 7cd1d7f8f608..b256cfbef344 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -87,6 +87,11 @@ int main(void)
87 DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context)); 87 DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
88 BLANK(); 88 BLANK();
89 DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT); 89 DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
90
91 /* constants */
92 DEFINE(_CLONE_VM, CLONE_VM);
93 DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);
94
90 return 0; 95 return 0;
91} 96}
92 97
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index c0b56b17927f..9e271ba009bf 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1004,13 +1004,10 @@ ENTRY(fast_syscall_kernel)
1004 1004
1005 rsr a0, DEPC # get syscall-nr 1005 rsr a0, DEPC # get syscall-nr
1006 _beqz a0, fast_syscall_spill_registers 1006 _beqz a0, fast_syscall_spill_registers
1007 1007 _beqi a0, __NR_xtensa, fast_syscall_xtensa
1008 addi a0, a0, -__NR_sysxtensa
1009 _beqz a0, fast_syscall_sysxtensa
1010 1008
1011 j kernel_exception 1009 j kernel_exception
1012 1010
1013
1014ENTRY(fast_syscall_user) 1011ENTRY(fast_syscall_user)
1015 1012
1016 /* Skip syscall. */ 1013 /* Skip syscall. */
@@ -1024,9 +1021,7 @@ ENTRY(fast_syscall_user)
1024 1021
1025 rsr a0, DEPC # get syscall-nr 1022 rsr a0, DEPC # get syscall-nr
1026 _beqz a0, fast_syscall_spill_registers 1023 _beqz a0, fast_syscall_spill_registers
1027 1024 _beqi a0, __NR_xtensa, fast_syscall_xtensa
1028 addi a0, a0, -__NR_sysxtensa
1029 _beqz a0, fast_syscall_sysxtensa
1030 1025
1031 j user_exception 1026 j user_exception
1032 1027
@@ -1047,18 +1042,19 @@ ENTRY(fast_syscall_unrecoverable)
1047/* 1042/*
1048 * sysxtensa syscall handler 1043 * sysxtensa syscall handler
1049 * 1044 *
1050 * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused); 1045 * int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused);
1051 * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused); 1046 * int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused);
1052 * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused); 1047 * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
1053 * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval); 1048 * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
1054 * a2 a6 a3 a4 a5 1049 * a2 a6 a3 a4 a5
1055 * 1050 *
1056 * Entry condition: 1051 * Entry condition:
1057 * 1052 *
1058 * a0: trashed, original value saved on stack (PT_AREG0) 1053 * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0)
1059 * a1: a1 1054 * a1: a1
1060 * a2: new stack pointer, original in DEPC 1055 * a2: new stack pointer, original in a0 and DEPC
1061 * a3: dispatch table 1056 * a3: dispatch table, original in excsave_1
1057 * a4..a15: unchanged
1062 * depc: a2, original value saved on stack (PT_DEPC) 1058 * depc: a2, original value saved on stack (PT_DEPC)
1063 * excsave_1: a3 1059 * excsave_1: a3
1064 * 1060 *
@@ -1091,59 +1087,62 @@ ENTRY(fast_syscall_unrecoverable)
1091#define CATCH \ 1087#define CATCH \
109267: 108867:
1093 1089
1094ENTRY(fast_syscall_sysxtensa) 1090ENTRY(fast_syscall_xtensa)
1095
1096 _beqz a6, 1f
1097 _blti a6, SYSXTENSA_COUNT, 2f
1098 1091
10991: j user_exception 1092 xsr a3, EXCSAVE_1 # restore a3, excsave1
1100
11012: xsr a3, EXCSAVE_1 # restore a3, excsave1
1102 s32i a7, a2, PT_AREG7
1103 1093
1094 s32i a7, a2, PT_AREG7 # we need an additional register
1104 movi a7, 4 # sizeof(unsigned int) 1095 movi a7, 4 # sizeof(unsigned int)
1105 access_ok a0, a3, a7, a2, .Leac 1096 access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
1106 1097
1107 _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset 1098 addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1
1108 _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg 1099 _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill
1109 _beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd 1100 _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
1110 1101
1111 /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */ 1102 /* Fall through for ATOMIC_CMP_SWP. */
1112 1103
1113.Lswp: /* Atomic compare and swap */ 1104.Lswp: /* Atomic compare and swap */
1114 1105
1115TRY l32i a7, a3, 0 # read old value 1106TRY l32i a0, a3, 0 # read old value
1116 bne a7, a4, 1f # same as old value? jump 1107 bne a0, a4, 1f # same as old value? jump
1117 s32i a5, a3, 0 # different, modify value 1108TRY s32i a5, a3, 0 # different, modify value
1118 movi a7, 1 # and return 1 1109 l32i a7, a2, PT_AREG7 # restore a7
1119 j .Lret 1110 l32i a0, a2, PT_AREG0 # restore a0
1120 1111 movi a2, 1 # and return 1
11211: movi a7, 0 # same values: return 0 1112 addi a6, a6, 1 # restore a6 (really necessary?)
1122 j .Lret 1113 rfe
1123
1124.Ladd: /* Atomic add */
1125.Lexg: /* Atomic (exchange) add */
1126 1114
1127TRY l32i a7, a3, 0 11151: l32i a7, a2, PT_AREG7 # restore a7
1128 add a4, a4, a7 1116 l32i a0, a2, PT_AREG0 # restore a0
1129 s32i a4, a3, 0 1117 movi a2, 0 # return 0 (note that we cannot set
1130 j .Lret 1118 addi a6, a6, 1 # restore a6 (really necessary?)
1119 rfe
1131 1120
1132.Lset: /* Atomic set */ 1121.Lnswp: /* Atomic set, add, and exg_add. */
1133 1122
1134TRY l32i a7, a3, 0 # read old value as return value 1123TRY l32i a7, a3, 0 # orig
1135 s32i a4, a3, 0 # write new value 1124 add a0, a4, a7 # + arg
1125 moveqz a0, a4, a6 # set
1126TRY s32i a0, a3, 0 # write new value
1136 1127
1137.Lret: mov a0, a2 1128 mov a0, a2
1138 mov a2, a7 1129 mov a2, a7
1139 l32i a7, a0, PT_AREG7 1130 l32i a7, a0, PT_AREG7 # restore a7
1140 l32i a3, a0, PT_AREG3 1131 l32i a0, a0, PT_AREG0 # restore a0
1141 l32i a0, a0, PT_AREG0 1132 addi a6, a6, 1 # restore a6 (really necessary?)
1142 rfe 1133 rfe
1143 1134
1144CATCH 1135CATCH
1145.Leac: movi a7, -EFAULT 1136.Leac: l32i a7, a2, PT_AREG7 # restore a7
1146 j .Lret 1137 l32i a0, a2, PT_AREG0 # restore a0
1138 movi a2, -EFAULT
1139 rfe
1140
1141.Lill: l32i a7, a2, PT_AREG0 # restore a7
1142 l32i a0, a2, PT_AREG0 # restore a0
1143 movi a2, -EINVAL
1144 rfe
1145
1147 1146
1148 1147
1149 1148
@@ -1907,6 +1906,103 @@ ENTRY(fast_coprocessor)
1907#endif /* XCHAL_EXTRA_SA_SIZE */ 1906#endif /* XCHAL_EXTRA_SA_SIZE */
1908 1907
1909/* 1908/*
1909 * System Calls.
1910 *
1911 * void system_call (struct pt_regs* regs, int exccause)
1912 * a2 a3
1913 */
1914
1915ENTRY(system_call)
1916 entry a1, 32
1917
1918 /* regs->syscall = regs->areg[2] */
1919
1920 l32i a3, a2, PT_AREG2
1921 mov a6, a2
1922 movi a4, do_syscall_trace_enter
1923 s32i a3, a2, PT_SYSCALL
1924 callx4 a4
1925
1926 /* syscall = sys_call_table[syscall_nr] */
1927
1928 movi a4, sys_call_table;
1929 movi a5, __NR_syscall_count
1930 movi a6, -ENOSYS
1931 bgeu a3, a5, 1f
1932
1933 addx4 a4, a3, a4
1934 l32i a4, a4, 0
1935 movi a5, sys_ni_syscall;
1936 beq a4, a5, 1f
1937
1938 /* Load args: arg0 - arg5 are passed via regs. */
1939
1940 l32i a6, a2, PT_AREG6
1941 l32i a7, a2, PT_AREG3
1942 l32i a8, a2, PT_AREG4
1943 l32i a9, a2, PT_AREG5
1944 l32i a10, a2, PT_AREG8
1945 l32i a11, a2, PT_AREG9
1946
1947 /* Pass one additional argument to the syscall: pt_regs (on stack) */
1948 s32i a2, a1, 0
1949
1950 callx4 a4
1951
19521: /* regs->areg[2] = return_value */
1953
1954 s32i a6, a2, PT_AREG2
1955 movi a4, do_syscall_trace_leave
1956 mov a6, a2
1957 callx4 a4
1958 retw
1959
1960
1961/*
1962 * Create a kernel thread
1963 *
1964 * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
1965 * a2 a2 a3 a4
1966 */
1967
1968ENTRY(kernel_thread)
1969 entry a1, 16
1970
1971 mov a5, a2 # preserve fn over syscall
1972 mov a7, a3 # preserve args over syscall
1973
1974 movi a3, _CLONE_VM | _CLONE_UNTRACED
1975 movi a2, __NR_clone
1976 or a6, a4, a3 # arg0: flags
1977 mov a3, a1 # arg1: sp
1978 syscall
1979
1980 beq a3, a1, 1f # branch if parent
1981 mov a6, a7 # args
1982 callx4 a5 # fn(args)
1983
1984 movi a2, __NR_exit
1985 syscall # return value of fn(args) still in a6
1986
19871: retw
1988
1989/*
1990 * Do a system call from kernel instead of calling sys_execve, so we end up
1991 * with proper pt_regs.
1992 *
1993 * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
1994 * a2 a2 a3 a4
1995 */
1996
1997ENTRY(kernel_execve)
1998 entry a1, 16
1999 mov a6, a2 # arg0 is in a6
2000 movi a2, __NR_execve
2001 syscall
2002
2003 retw
2004
2005/*
1910 * Task switch. 2006 * Task switch.
1911 * 2007 *
1912 * struct task* _switch_to (struct task* prev, struct task* next) 2008 * struct task* _switch_to (struct task* prev, struct task* next)
@@ -1964,33 +2060,9 @@ ENTRY(ret_from_fork)
1964 movi a4, schedule_tail 2060 movi a4, schedule_tail
1965 callx4 a4 2061 callx4 a4
1966 2062
1967 movi a4, do_syscall_trace 2063 movi a4, do_syscall_trace_leave
2064 mov a6, a1
1968 callx4 a4 2065 callx4 a4
1969 2066
1970 j common_exception_return 2067 j common_exception_return
1971 2068
1972
1973
1974/*
1975 * Table of syscalls
1976 */
1977
1978.data
1979.align 4
1980.global sys_call_table
1981sys_call_table:
1982
1983#define SYSCALL(call, narg) .word call
1984#include "syscalls.h"
1985
1986/*
1987 * Number of arguments of each syscall
1988 */
1989
1990.global sys_narg_table
1991sys_narg_table:
1992
1993#undef SYSCALL
1994#define SYSCALL(call, narg) .byte narg
1995#include "syscalls.h"
1996
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 3785f3481d71..795bd5ac6f4c 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -161,36 +161,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
161 161
162 162
163/* 163/*
164 * Create a kernel thread
165 */
166
167int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
168{
169 long retval;
170 __asm__ __volatile__
171 ("mov a5, %4\n\t" /* preserve fn in a5 */
172 "mov a6, %3\n\t" /* preserve and setup arg in a6 */
173 "movi a2, %1\n\t" /* load __NR_clone for syscall*/
174 "mov a3, sp\n\t" /* sp check and sys_clone */
175 "mov a4, %5\n\t" /* load flags for syscall */
176 "syscall\n\t"
177 "beq a3, sp, 1f\n\t" /* branch if parent */
178 "callx4 a5\n\t" /* call fn */
179 "movi a2, %2\n\t" /* load __NR_exit for syscall */
180 "mov a3, a6\n\t" /* load fn return value */
181 "syscall\n"
182 "1:\n\t"
183 "mov %0, a2\n\t" /* parent returns zero */
184 :"=r" (retval)
185 :"i" (__NR_clone), "i" (__NR_exit),
186 "r" (arg), "r" (fn),
187 "r" (flags | CLONE_VM)
188 : "a2", "a3", "a4", "a5", "a6" );
189 return retval;
190}
191
192
193/*
194 * These bracket the sleeping functions.. 164 * These bracket the sleeping functions..
195 */ 165 */
196 166
@@ -452,3 +422,44 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
452{ 422{
453 return dump_task_fpu(regs, current, r); 423 return dump_task_fpu(regs, current, r);
454} 424}
425
426asmlinkage
427long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
428 void __user *parent_tid, void *child_tls,
429 void __user *child_tid, long a5,
430 struct pt_regs *regs)
431{
432 if (!newsp)
433 newsp = regs->areg[1];
434 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
435}
436
437/*
438 * * xtensa_execve() executes a new program.
439 * */
440
441asmlinkage
442long xtensa_execve(char __user *name, char __user * __user *argv,
443 char __user * __user *envp,
444 long a3, long a4, long a5,
445 struct pt_regs *regs)
446{
447 long error;
448 char * filename;
449
450 filename = getname(name);
451 error = PTR_ERR(filename);
452 if (IS_ERR(filename))
453 goto out;
454 // FIXME: release coprocessor??
455 error = do_execve(filename, argv, envp, regs);
456 if (error == 0) {
457 task_lock(current);
458 current->ptrace &= ~PT_DTRACE;
459 task_unlock(current);
460 }
461 putname(filename);
462out:
463 return error;
464}
465
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 604c3c3c6759..8b6d3d0623b6 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -332,12 +332,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
332 332
333void do_syscall_trace(void) 333void do_syscall_trace(void)
334{ 334{
335 if (!test_thread_flag(TIF_SYSCALL_TRACE))
336 return;
337
338 if (!(current->ptrace & PT_PTRACED))
339 return;
340
341 /* 335 /*
342 * The 0x80 provides a way for the tracing parent to distinguish 336 * The 0x80 provides a way for the tracing parent to distinguish
343 * between a syscall stop and SIGTRAP delivery 337 * between a syscall stop and SIGTRAP delivery
@@ -354,3 +348,23 @@ void do_syscall_trace(void)
354 current->exit_code = 0; 348 current->exit_code = 0;
355 } 349 }
356} 350}
351
352void do_syscall_trace_enter(struct pt_regs *regs)
353{
354 if (test_thread_flag(TIF_SYSCALL_TRACE)
355 && (current->ptrace & PT_PTRACED))
356 do_syscall_trace();
357
358#if 0
359 if (unlikely(current->audit_context))
360 audit_syscall_entry(current, AUDIT_ARCH_XTENSA..);
361#endif
362}
363
364void do_syscall_trace_leave(struct pt_regs *regs)
365{
366 if ((test_thread_flag(TIF_SYSCALL_TRACE))
367 && (current->ptrace & PT_PTRACED))
368 do_syscall_trace();
369}
370
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 6af7f4145990..c6d9880a4cdb 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -46,7 +46,7 @@ extern struct task_struct *coproc_owners[];
46 * Atomically swap in the new signal mask, and wait for a signal. 46 * Atomically swap in the new signal mask, and wait for a signal.
47 */ 47 */
48 48
49int sys_sigsuspend(struct pt_regs *regs) 49int xtensa_sigsuspend(struct pt_regs *regs)
50{ 50{
51 old_sigset_t mask = (old_sigset_t) regs->areg[3]; 51 old_sigset_t mask = (old_sigset_t) regs->areg[3];
52 sigset_t saveset; 52 sigset_t saveset;
@@ -68,7 +68,7 @@ int sys_sigsuspend(struct pt_regs *regs)
68} 68}
69 69
70asmlinkage int 70asmlinkage int
71sys_rt_sigsuspend(struct pt_regs *regs) 71xtensa_rt_sigsuspend(struct pt_regs *regs)
72{ 72{
73 sigset_t *unewset = (sigset_t *) regs->areg[4]; 73 sigset_t *unewset = (sigset_t *) regs->areg[4];
74 size_t sigsetsize = (size_t) regs->areg[3]; 74 size_t sigsetsize = (size_t) regs->areg[3];
@@ -96,7 +96,7 @@ sys_rt_sigsuspend(struct pt_regs *regs)
96} 96}
97 97
98asmlinkage int 98asmlinkage int
99sys_sigaction(int sig, const struct old_sigaction *act, 99xtensa_sigaction(int sig, const struct old_sigaction *act,
100 struct old_sigaction *oact) 100 struct old_sigaction *oact)
101{ 101{
102 struct k_sigaction new_ka, old_ka; 102 struct k_sigaction new_ka, old_ka;
@@ -128,7 +128,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
128} 128}
129 129
130asmlinkage int 130asmlinkage int
131sys_sigaltstack(struct pt_regs *regs) 131xtensa_sigaltstack(struct pt_regs *regs)
132{ 132{
133 const stack_t *uss = (stack_t *) regs->areg[4]; 133 const stack_t *uss = (stack_t *) regs->areg[4];
134 stack_t *uoss = (stack_t *) regs->areg[3]; 134 stack_t *uoss = (stack_t *) regs->areg[3];
@@ -350,7 +350,7 @@ setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
350 return err; 350 return err;
351} 351}
352 352
353asmlinkage int sys_sigreturn(struct pt_regs *regs) 353asmlinkage int xtensa_sigreturn(struct pt_regs *regs)
354{ 354{
355 struct sigframe *frame = (struct sigframe *)regs->areg[1]; 355 struct sigframe *frame = (struct sigframe *)regs->areg[1];
356 sigset_t set; 356 sigset_t set;
@@ -382,7 +382,7 @@ badframe:
382 return 0; 382 return 0;
383} 383}
384 384
385asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) 385asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
386{ 386{
387 struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1]; 387 struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
388 sigset_t set; 388 sigset_t set;
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
new file mode 100644
index 000000000000..418268f49766
--- /dev/null
+++ b/arch/xtensa/kernel/syscall.c
@@ -0,0 +1,95 @@
1/*
2 * arch/xtensa/kernel/syscall.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#include <asm/uaccess.h>
19#include <asm/syscalls.h>
20#include <asm/unistd.h>
21#include <linux/linkage.h>
22#include <linux/stringify.h>
23#include <linux/errno.h>
24#include <linux/syscalls.h>
25#include <linux/file.h>
26#include <linux/fs.h>
27#include <linux/mman.h>
28#include <linux/shm.h>
29
30typedef void (*syscall_t)(void);
31
32syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
33 [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
34
35#undef __SYSCALL
36#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
37#undef _XTENSA_UNISTD_H
38#undef __KERNEL_SYSCALLS__
39#include <asm/unistd.h>
40};
41
42/*
43 * xtensa_pipe() is the normal C calling standard for creating a pipe. It's not
44 * the way unix traditional does this, though.
45 */
46
47asmlinkage long xtensa_pipe(int __user *userfds)
48{
49 int fd[2];
50 int error;
51
52 error = do_pipe(fd);
53 if (!error) {
54 if (copy_to_user(userfds, fd, 2 * sizeof(int)))
55 error = -EFAULT;
56 }
57 return error;
58}
59
60
61asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len,
62 unsigned long prot, unsigned long flags,
63 unsigned long fd, unsigned long pgoff)
64{
65 int error = -EBADF;
66 struct file * file = NULL;
67
68 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
69 if (!(flags & MAP_ANONYMOUS)) {
70 file = fget(fd);
71 if (!file)
72 goto out;
73 }
74
75 down_write(&current->mm->mmap_sem);
76 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
77 up_write(&current->mm->mmap_sem);
78
79 if (file)
80 fput(file);
81out:
82 return error;
83}
84
85asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
86{
87 unsigned long ret;
88 long err;
89
90 err = do_shmat(shmid, shmaddr, shmflg, &ret);
91 if (err)
92 return err;
93 return (long)ret;
94}
95
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}
diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h
deleted file mode 100644
index 216c10a31501..000000000000
--- a/arch/xtensa/kernel/syscalls.h
+++ /dev/null
@@ -1,247 +0,0 @@
1/*
2 * arch/xtensa/kernel/syscalls.h
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) 1995, 1996, 1997, 1998 by Ralf Baechle
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 *
11 * Changes by Joe Taylor <joe@tensilica.com>
12 */
13
14/*
15 * This file is being included twice - once to build a list of all
16 * syscalls and once to build a table of how many arguments each syscall
17 * accepts. Syscalls that receive a pointer to the saved registers are
18 * marked as having zero arguments.
19 *
20 * The binary compatibility calls are in a separate list.
21 *
22 * Entry '0' used to be system_call. It's removed to disable indirect
23 * system calls for now so user tasks can't recurse. See mips'
24 * sys_syscall for a comparable example.
25 */
26
27SYSCALL(0, 0) /* 00 */
28SYSCALL(sys_exit, 1)
29SYSCALL(sys_ni_syscall, 0)
30SYSCALL(sys_read, 3)
31SYSCALL(sys_write, 3)
32SYSCALL(sys_open, 3) /* 05 */
33SYSCALL(sys_close, 1)
34SYSCALL(sys_ni_syscall, 3)
35SYSCALL(sys_creat, 2)
36SYSCALL(sys_link, 2)
37SYSCALL(sys_unlink, 1) /* 10 */
38SYSCALL(sys_execve, 0)
39SYSCALL(sys_chdir, 1)
40SYSCALL(sys_ni_syscall, 1)
41SYSCALL(sys_mknod, 3)
42SYSCALL(sys_chmod, 2) /* 15 */
43SYSCALL(sys_lchown, 3)
44SYSCALL(sys_ni_syscall, 0)
45SYSCALL(sys_newstat, 2)
46SYSCALL(sys_lseek, 3)
47SYSCALL(sys_getpid, 0) /* 20 */
48SYSCALL(sys_mount, 5)
49SYSCALL(sys_ni_syscall, 1)
50SYSCALL(sys_setuid, 1)
51SYSCALL(sys_getuid, 0)
52SYSCALL(sys_ni_syscall, 1) /* 25 */
53SYSCALL(sys_ptrace, 4)
54SYSCALL(sys_ni_syscall, 1)
55SYSCALL(sys_newfstat, 2)
56SYSCALL(sys_ni_syscall, 0)
57SYSCALL(sys_utime, 2) /* 30 */
58SYSCALL(sys_ni_syscall, 0)
59SYSCALL(sys_ni_syscall, 0)
60SYSCALL(sys_access, 2)
61SYSCALL(sys_ni_syscall, 1)
62SYSCALL(sys_ni_syscall, 0) /* 35 */
63SYSCALL(sys_sync, 0)
64SYSCALL(sys_kill, 2)
65SYSCALL(sys_rename, 2)
66SYSCALL(sys_mkdir, 2)
67SYSCALL(sys_rmdir, 1) /* 40 */
68SYSCALL(sys_dup, 1)
69SYSCALL(sys_pipe, 1)
70SYSCALL(sys_times, 1)
71SYSCALL(sys_ni_syscall, 0)
72SYSCALL(sys_brk, 1) /* 45 */
73SYSCALL(sys_setgid, 1)
74SYSCALL(sys_getgid, 0)
75SYSCALL(sys_ni_syscall, 0)
76SYSCALL(sys_geteuid, 0)
77SYSCALL(sys_getegid, 0) /* 50 */
78SYSCALL(sys_acct, 1)
79SYSCALL(sys_umount, 2)
80SYSCALL(sys_ni_syscall, 0)
81SYSCALL(sys_ioctl, 3)
82SYSCALL(sys_fcntl, 3) /* 55 */
83SYSCALL(sys_ni_syscall, 2)
84SYSCALL(sys_setpgid, 2)
85SYSCALL(sys_ni_syscall, 0)
86SYSCALL(sys_ni_syscall, 0)
87SYSCALL(sys_umask, 1) /* 60 */
88SYSCALL(sys_chroot, 1)
89SYSCALL(sys_ustat, 2)
90SYSCALL(sys_dup2, 2)
91SYSCALL(sys_getppid, 0)
92SYSCALL(sys_ni_syscall, 0) /* 65 */
93SYSCALL(sys_setsid, 0)
94SYSCALL(sys_sigaction, 3)
95SYSCALL(sys_ni_syscall, 0)
96SYSCALL(sys_ni_syscall, 1)
97SYSCALL(sys_setreuid, 2) /* 70 */
98SYSCALL(sys_setregid, 2)
99SYSCALL(sys_sigsuspend, 0)
100SYSCALL(sys_ni_syscall, 1)
101SYSCALL(sys_sethostname, 2)
102SYSCALL(sys_setrlimit, 2) /* 75 */
103SYSCALL(sys_getrlimit, 2)
104SYSCALL(sys_getrusage, 2)
105SYSCALL(sys_gettimeofday, 2)
106SYSCALL(sys_settimeofday, 2)
107SYSCALL(sys_getgroups, 2) /* 80 */
108SYSCALL(sys_setgroups, 2)
109SYSCALL(sys_ni_syscall, 0)
110SYSCALL(sys_symlink, 2)
111SYSCALL(sys_newlstat, 2)
112SYSCALL(sys_readlink, 3) /* 85 */
113SYSCALL(sys_uselib, 1)
114SYSCALL(sys_swapon, 2)
115SYSCALL(sys_reboot, 3)
116SYSCALL(sys_ni_syscall, 3)
117SYSCALL(sys_ni_syscall, 6) /* 90 */
118SYSCALL(sys_munmap, 2)
119SYSCALL(sys_truncate, 2)
120SYSCALL(sys_ftruncate, 2)
121SYSCALL(sys_fchmod, 2)
122SYSCALL(sys_fchown, 3) /* 95 */
123SYSCALL(sys_getpriority, 2)
124SYSCALL(sys_setpriority, 3)
125SYSCALL(sys_ni_syscall, 0)
126SYSCALL(sys_statfs, 2)
127SYSCALL(sys_fstatfs, 2) /* 100 */
128SYSCALL(sys_ni_syscall, 3)
129SYSCALL(sys_ni_syscall, 2)
130SYSCALL(sys_syslog, 3)
131SYSCALL(sys_setitimer, 3)
132SYSCALL(sys_getitimer, 2) /* 105 */
133SYSCALL(sys_newstat, 2)
134SYSCALL(sys_newlstat, 2)
135SYSCALL(sys_newfstat, 2)
136SYSCALL(sys_uname, 1)
137SYSCALL(sys_ni_syscall, 0) /* 110 */
138SYSCALL(sys_vhangup, 0)
139SYSCALL(sys_ni_syscall, 0)
140SYSCALL(sys_ni_syscall, 0)
141SYSCALL(sys_wait4, 4)
142SYSCALL(sys_swapoff, 1) /* 115 */
143SYSCALL(sys_sysinfo, 1)
144SYSCALL(sys_ni_syscall, 0)
145SYSCALL(sys_fsync, 1)
146SYSCALL(sys_sigreturn, 0)
147SYSCALL(sys_clone, 0) /* 120 */
148SYSCALL(sys_setdomainname, 2)
149SYSCALL(sys_newuname, 1)
150SYSCALL(sys_ni_syscall, 0)
151SYSCALL(sys_adjtimex, 1)
152SYSCALL(sys_mprotect, 3) /* 125 */
153SYSCALL(sys_ni_syscall, 3)
154SYSCALL(sys_ni_syscall, 2)
155SYSCALL(sys_init_module, 2)
156SYSCALL(sys_delete_module, 1)
157SYSCALL(sys_ni_syscall, 1) /* 130 */
158SYSCALL(sys_quotactl, 0)
159SYSCALL(sys_getpgid, 1)
160SYSCALL(sys_fchdir, 1)
161SYSCALL(sys_bdflush, 2)
162SYSCALL(sys_sysfs, 3) /* 135 */
163SYSCALL(sys_personality, 1)
164SYSCALL(sys_ni_syscall, 0)
165SYSCALL(sys_setfsuid, 1)
166SYSCALL(sys_setfsgid, 1)
167SYSCALL(sys_llseek, 5) /* 140 */
168SYSCALL(sys_getdents, 3)
169SYSCALL(sys_select, 5)
170SYSCALL(sys_flock, 2)
171SYSCALL(sys_msync, 3)
172SYSCALL(sys_readv, 3) /* 145 */
173SYSCALL(sys_writev, 3)
174SYSCALL(sys_ni_syscall, 3)
175SYSCALL(sys_ni_syscall, 3)
176SYSCALL(sys_ni_syscall, 4) /* handled in fast syscall handler. */
177SYSCALL(sys_ni_syscall, 0) /* 150 */
178SYSCALL(sys_getsid, 1)
179SYSCALL(sys_fdatasync, 1)
180SYSCALL(sys_sysctl, 1)
181SYSCALL(sys_mlock, 2)
182SYSCALL(sys_munlock, 2) /* 155 */
183SYSCALL(sys_mlockall, 1)
184SYSCALL(sys_munlockall, 0)
185SYSCALL(sys_sched_setparam,2)
186SYSCALL(sys_sched_getparam,2)
187SYSCALL(sys_sched_setscheduler,3) /* 160 */
188SYSCALL(sys_sched_getscheduler,1)
189SYSCALL(sys_sched_yield,0)
190SYSCALL(sys_sched_get_priority_max,1)
191SYSCALL(sys_sched_get_priority_min,1)
192SYSCALL(sys_sched_rr_get_interval,2) /* 165 */
193SYSCALL(sys_nanosleep,2)
194SYSCALL(sys_mremap,4)
195SYSCALL(sys_accept, 3)
196SYSCALL(sys_bind, 3)
197SYSCALL(sys_connect, 3) /* 170 */
198SYSCALL(sys_getpeername, 3)
199SYSCALL(sys_getsockname, 3)
200SYSCALL(sys_getsockopt, 5)
201SYSCALL(sys_listen, 2)
202SYSCALL(sys_recv, 4) /* 175 */
203SYSCALL(sys_recvfrom, 6)
204SYSCALL(sys_recvmsg, 3)
205SYSCALL(sys_send, 4)
206SYSCALL(sys_sendmsg, 3)
207SYSCALL(sys_sendto, 6) /* 180 */
208SYSCALL(sys_setsockopt, 5)
209SYSCALL(sys_shutdown, 2)
210SYSCALL(sys_socket, 3)
211SYSCALL(sys_socketpair, 4)
212SYSCALL(sys_setresuid, 3) /* 185 */
213SYSCALL(sys_getresuid, 3)
214SYSCALL(sys_ni_syscall, 5)
215SYSCALL(sys_poll, 3)
216SYSCALL(sys_nfsservctl, 3)
217SYSCALL(sys_setresgid, 3) /* 190 */
218SYSCALL(sys_getresgid, 3)
219SYSCALL(sys_prctl, 5)
220SYSCALL(sys_rt_sigreturn, 0)
221SYSCALL(sys_rt_sigaction, 4)
222SYSCALL(sys_rt_sigprocmask, 4) /* 195 */
223SYSCALL(sys_rt_sigpending, 2)
224SYSCALL(sys_rt_sigtimedwait, 4)
225SYSCALL(sys_rt_sigqueueinfo, 3)
226SYSCALL(sys_rt_sigsuspend, 0)
227SYSCALL(sys_pread64, 5) /* 200 */
228SYSCALL(sys_pwrite64, 5)
229SYSCALL(sys_chown, 3)
230SYSCALL(sys_getcwd, 2)
231SYSCALL(sys_capget, 2)
232SYSCALL(sys_capset, 2) /* 205 */
233SYSCALL(sys_sigaltstack, 0)
234SYSCALL(sys_sendfile, 4)
235SYSCALL(sys_ni_syscall, 0)
236SYSCALL(sys_ni_syscall, 0)
237SYSCALL(sys_mmap, 6) /* 210 */
238SYSCALL(sys_truncate64, 2)
239SYSCALL(sys_ftruncate64, 2)
240SYSCALL(sys_stat64, 2)
241SYSCALL(sys_lstat64, 2)
242SYSCALL(sys_fstat64, 2) /* 215 */
243SYSCALL(sys_pivot_root, 2)
244SYSCALL(sys_mincore, 3)
245SYSCALL(sys_madvise, 3)
246SYSCALL(sys_getdents64, 3)
247SYSCALL(sys_ni_syscall, 0) /* 220 */