Commit f673c032 authored by Arnd Bergmann's avatar Arnd Bergmann

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: default avatarArnd Bergmann <arnd@arndb.de>
parent 78229db4
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
extra-y := head.o vmlinux.lds extra-y := head.o vmlinux.lds
obj-y += entry.o init_task.o irq.o process.o ptrace.o \ 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 obj-$(CONFIG_MODULES) += module.o
...@@ -400,6 +400,8 @@ ENTRY(handle_sys) ...@@ -400,6 +400,8 @@ ENTRY(handle_sys)
sw r4, [r0, PT_ORIG_R4] #for restart syscall sw r4, [r0, PT_ORIG_R4] #for restart syscall
sw r7, [r0, PT_ORIG_R7] #for restart syscall sw r7, [r0, PT_ORIG_R7] #for restart syscall
sw r27, [r0, PT_IS_SYSCALL] # it from 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 lw r9, [r0, PT_EPC] # skip syscall on return
addi r9, 4 addi r9, 4
...@@ -408,19 +410,14 @@ ENTRY(handle_sys) ...@@ -408,19 +410,14 @@ ENTRY(handle_sys)
cmpi.c r27, __NR_syscalls # check syscall number cmpi.c r27, __NR_syscalls # check syscall number
bgtu illegal_syscall bgtu illegal_syscall
slli r8, r27, 3 # get syscall routine slli r8, r27, 2 # get syscall routine
la r11, sys_call_table la r11, sys_call_table
add r11, r11, r8 add r11, r11, r8
lw r10, [r11] # get syscall entry lw r10, [r11] # get syscall entry
lw r11, [r11, 4] # get number of args
cmpz.c r10 cmpz.c r10
beq illegal_syscall beq illegal_syscall
cmpi.c r11, 4 # more than 4 arguments?
bgtu stackargs
stack_done:
lw r8, [r28, TI_FLAGS] lw r8, [r28, TI_FLAGS]
li r9, _TIF_SYSCALL_TRACE li r9, _TIF_SYSCALL_TRACE
and.c r8, r8, r9 and.c r8, r8, r9
...@@ -475,44 +472,6 @@ syscall_trace_entry: ...@@ -475,44 +472,6 @@ syscall_trace_entry:
1: sw r4, [r0, PT_R2] # result 1: sw r4, [r0, PT_R2] # result
j syscall_exit 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: illegal_syscall:
ldi r4, -ENOSYS # error ldi r4, -ENOSYS # error
sw r4, [r0, PT_ORIG_R4] sw r4, [r0, PT_ORIG_R4]
......
#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>
};
...@@ -75,14 +75,7 @@ int score_clone(struct pt_regs *regs) ...@@ -75,14 +75,7 @@ int score_clone(struct pt_regs *regs)
if (!newsp) if (!newsp)
newsp = regs->regs[0]; newsp = regs->regs[0];
parent_tidptr = (int __user *)regs->regs[6]; parent_tidptr = (int __user *)regs->regs[6];
child_tidptr = (int __user *)regs->regs[8];
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;
}
return do_fork(clone_flags, newsp, regs, 0, return do_fork(clone_flags, newsp, regs, 0,
parent_tidptr, child_tidptr); parent_tidptr, child_tidptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment