aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2009-06-19 05:31:54 -0400
committerArnd Bergmann <arnd@arndb.de>2009-06-19 08:10:33 -0400
commitf673c032ed13ed8f3fda5922c2190da2892398bc (patch)
tree8e1145ed21188c77ffdfacba2b22a529c8ddb938
parent78229db4c4f78f27ecf772fe7489a70530ba9862 (diff)
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>
-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 @@
5extra-y := head.o vmlinux.lds 5extra-y := head.o vmlinux.lds
6 6
7obj-y += entry.o init_task.o irq.o process.o ptrace.o \ 7obj-y += entry.o init_task.o irq.o process.o ptrace.o \
8 setup.o signal.o sys_score.o time.o traps.o 8 setup.o signal.o sys_score.o time.o traps.o \
9 sys_call_table.o
9 10
10obj-$(CONFIG_MODULES) += module.o 11obj-$(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)
400 sw r4, [r0, PT_ORIG_R4] #for restart syscall 400 sw r4, [r0, PT_ORIG_R4] #for restart syscall
401 sw r7, [r0, PT_ORIG_R7] #for restart syscall 401 sw r7, [r0, PT_ORIG_R7] #for restart syscall
402 sw r27, [r0, PT_IS_SYSCALL] # it from syscall 402 sw r27, [r0, PT_IS_SYSCALL] # it from syscall
403 sw r8, [r0, 16] # argument 5 from user r8
404 sw r9, [r0, 20] # argument 6 from user r9
403 405
404 lw r9, [r0, PT_EPC] # skip syscall on return 406 lw r9, [r0, PT_EPC] # skip syscall on return
405 addi r9, 4 407 addi r9, 4
@@ -408,19 +410,14 @@ ENTRY(handle_sys)
408 cmpi.c r27, __NR_syscalls # check syscall number 410 cmpi.c r27, __NR_syscalls # check syscall number
409 bgtu illegal_syscall 411 bgtu illegal_syscall
410 412
411 slli r8, r27, 3 # get syscall routine 413 slli r8, r27, 2 # get syscall routine
412 la r11, sys_call_table 414 la r11, sys_call_table
413 add r11, r11, r8 415 add r11, r11, r8
414 lw r10, [r11] # get syscall entry 416 lw r10, [r11] # get syscall entry
415 lw r11, [r11, 4] # get number of args
416 417
417 cmpz.c r10 418 cmpz.c r10
418 beq illegal_syscall 419 beq illegal_syscall
419 420
420 cmpi.c r11, 4 # more than 4 arguments?
421 bgtu stackargs
422
423stack_done:
424 lw r8, [r28, TI_FLAGS] 421 lw r8, [r28, TI_FLAGS]
425 li r9, _TIF_SYSCALL_TRACE 422 li r9, _TIF_SYSCALL_TRACE
426 and.c r8, r8, r9 423 and.c r8, r8, r9
@@ -475,44 +472,6 @@ syscall_trace_entry:
4751: sw r4, [r0, PT_R2] # result 4721: sw r4, [r0, PT_R2] # result
476 j syscall_exit 473 j syscall_exit
477 474
478stackargs:
479 lw r8, [r0, PT_R0]
480 andri.c r9, r8, 3 # test whether user sp is align a word
481 bne bad_stack
482 subi r11, 5
483 slli r9, r11, 2
484 add.c r9, r9, r8
485
486 bmi bad_stack
487 la r9, 3f # calculate branch address
488 slli r11, r11, 3
489 sub r9, r9, r11
490 br r9
491
4922: lw r9, [r8, 20] # argument 6 from usp
493 sw r9, [r0, 20]
494
4953: lw r9, [r8, 16] # argument 5 from usp
496 sw r9, [r0, 16]
497 j stack_done
498
499 .section __ex_table,"a"
500 .word 2b, bad_stack
501 .word 3b, bad_stack
502 .previous
503
504 /*
505 * The stackpointer for a call with more than 4 arguments is bad.
506 * We probably should handle this case a bit more drastic.
507 */
508bad_stack:
509 neg r27, r27 # error
510 sw r27, [r0, PT_ORIG_R4]
511 sw r27, [r0, PT_R4]
512 ldi r8, 1 # set error flag
513 sw r8, [r0, PT_R7]
514 j syscall_return
515
516illegal_syscall: 475illegal_syscall:
517 ldi r4, -ENOSYS # error 476 ldi r4, -ENOSYS # error
518 sw r4, [r0, PT_ORIG_R4] 477 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 @@
1#include <linux/syscalls.h>
2#include <linux/signal.h>
3#include <linux/unistd.h>
4
5#include <asm/syscalls.h>
6
7#undef __SYSCALL
8#define __SYSCALL(nr, call) [nr] = (call),
9
10void *sys_call_table[__NR_syscalls] = {
11#include <asm/unistd.h>
12};
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)
75 if (!newsp) 75 if (!newsp)
76 newsp = regs->regs[0]; 76 newsp = regs->regs[0];
77 parent_tidptr = (int __user *)regs->regs[6]; 77 parent_tidptr = (int __user *)regs->regs[6];
78 78 child_tidptr = (int __user *)regs->regs[8];
79 child_tidptr = NULL;
80 if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
81 int __user *__user *usp = (int __user *__user *)regs->regs[0];
82
83 if (get_user(child_tidptr, &usp[4]))
84 return -EFAULT;
85 }
86 79
87 return do_fork(clone_flags, newsp, regs, 0, 80 return do_fork(clone_flags, newsp, regs, 0,
88 parent_tidptr, child_tidptr); 81 parent_tidptr, child_tidptr);