summaryrefslogtreecommitdiffstats
path: root/arch/score
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2009-06-19 11:31:54 +0200
committerArnd Bergmann <arnd@arndb.de>2009-06-19 14:10:33 +0200
commitf673c032ed13ed8f3fda5922c2190da2892398bc (patch)
tree8e1145ed21188c77ffdfacba2b22a529c8ddb938 /arch/score
parent78229db4c4f78f27ecf772fe7489a70530ba9862 (diff)
downloadlinux-f673c032ed13ed8f3fda5922c2190da2892398bc.tar.bz2
score: add generic sys_call_table
This adds back a sys_call_table to the score architecture, which got lost in the conversion to the generic unistd.h file. It's rather worrying that the code got submitted without a system call table, which evidently means that it got zero testing. Since the system call table has a different layout from the old one (which was modeled after the mips-o32 one), I also try to fix the entry.S path to use it. In the modified calling conventions, all system call arguments are passed as registers r4 through r9, instead of r4 through r7 plus stack for the fifth and sixth argument. This matches what other architectures to when they normally pass arguments on the stack. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/score')
-rw-r--r--arch/score/kernel/Makefile3
-rw-r--r--arch/score/kernel/entry.S47
-rw-r--r--arch/score/kernel/sys_call_table.c12
-rw-r--r--arch/score/kernel/sys_score.c9
4 files changed, 18 insertions, 53 deletions
diff --git a/arch/score/kernel/Makefile b/arch/score/kernel/Makefile
index 1e5de89d5c73..f218673b5d3d 100644
--- a/arch/score/kernel/Makefile
+++ b/arch/score/kernel/Makefile
@@ -5,6 +5,7 @@
extra-y := head.o vmlinux.lds
obj-y += entry.o init_task.o irq.o process.o ptrace.o \
- setup.o signal.o sys_score.o time.o traps.o
+ setup.o signal.o sys_score.o time.o traps.o \
+ sys_call_table.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S
index 0af89b2f16b0..2f169175bbd9 100644
--- a/arch/score/kernel/entry.S
+++ b/arch/score/kernel/entry.S
@@ -400,6 +400,8 @@ ENTRY(handle_sys)
sw r4, [r0, PT_ORIG_R4] #for restart syscall
sw r7, [r0, PT_ORIG_R7] #for restart syscall
sw r27, [r0, PT_IS_SYSCALL] # it from syscall
+ sw r8, [r0, 16] # argument 5 from user r8
+ sw r9, [r0, 20] # argument 6 from user r9
lw r9, [r0, PT_EPC] # skip syscall on return
addi r9, 4
@@ -408,19 +410,14 @@ ENTRY(handle_sys)
cmpi.c r27, __NR_syscalls # check syscall number
bgtu illegal_syscall
- slli r8, r27, 3 # get syscall routine
+ slli r8, r27, 2 # get syscall routine
la r11, sys_call_table
add r11, r11, r8
lw r10, [r11] # get syscall entry
- lw r11, [r11, 4] # get number of args
cmpz.c r10
beq illegal_syscall
- cmpi.c r11, 4 # more than 4 arguments?
- bgtu stackargs
-
-stack_done:
lw r8, [r28, TI_FLAGS]
li r9, _TIF_SYSCALL_TRACE
and.c r8, r8, r9
@@ -475,44 +472,6 @@ syscall_trace_entry:
1: sw r4, [r0, PT_R2] # result
j syscall_exit
-stackargs:
- lw r8, [r0, PT_R0]
- andri.c r9, r8, 3 # test whether user sp is align a word
- bne bad_stack
- subi r11, 5
- slli r9, r11, 2
- add.c r9, r9, r8
-
- bmi bad_stack
- la r9, 3f # calculate branch address
- slli r11, r11, 3
- sub r9, r9, r11
- br r9
-
-2: lw r9, [r8, 20] # argument 6 from usp
- sw r9, [r0, 20]
-
-3: lw r9, [r8, 16] # argument 5 from usp
- sw r9, [r0, 16]
- j stack_done
-
- .section __ex_table,"a"
- .word 2b, bad_stack
- .word 3b, bad_stack
- .previous
-
- /*
- * The stackpointer for a call with more than 4 arguments is bad.
- * We probably should handle this case a bit more drastic.
- */
-bad_stack:
- neg r27, r27 # error
- sw r27, [r0, PT_ORIG_R4]
- sw r27, [r0, PT_R4]
- ldi r8, 1 # set error flag
- sw r8, [r0, PT_R7]
- j syscall_return
-
illegal_syscall:
ldi r4, -ENOSYS # error
sw r4, [r0, PT_ORIG_R4]
diff --git a/arch/score/kernel/sys_call_table.c b/arch/score/kernel/sys_call_table.c
new file mode 100644
index 000000000000..287369b88c43
--- /dev/null
+++ b/arch/score/kernel/sys_call_table.c
@@ -0,0 +1,12 @@
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c
index 68655f4cbce9..331886104325 100644
--- a/arch/score/kernel/sys_score.c
+++ b/arch/score/kernel/sys_score.c
@@ -75,14 +75,7 @@ int score_clone(struct pt_regs *regs)
if (!newsp)
newsp = regs->regs[0];
parent_tidptr = (int __user *)regs->regs[6];
-
- child_tidptr = NULL;
- if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
- int __user *__user *usp = (int __user *__user *)regs->regs[0];
-
- if (get_user(child_tidptr, &usp[4]))
- return -EFAULT;
- }
+ child_tidptr = (int __user *)regs->regs[8];
return do_fork(clone_flags, newsp, regs, 0,
parent_tidptr, child_tidptr);