aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel
diff options
context:
space:
mode:
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 */