Commit 71e25a79 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: syscall numbers > 255.

Add support for system calls with numbers > 255.
parent 2e1e5016
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/offsets.h> #include <asm/offsets.h>
#include <asm/unistd.h>
/* /*
* Stack layout for the system_call stack entry. * Stack layout for the system_call stack entry.
...@@ -97,8 +98,7 @@ entry_base: ...@@ -97,8 +98,7 @@ entry_base:
stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst. stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst.
mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
mvc SP_PSW(8,%r15),\psworg # move user PSW to stack mvc SP_PSW(8,%r15),\psworg # move user PSW to stack
la %r0,\psworg # store trap indication mvc SP_TRAP(4,%r15),BASED(.L\psworg) # store trap indication
st %r0,SP_TRAP(%r15)
xc 0(4,%r15),0(%r15) # clear back chain xc 0(4,%r15),0(%r15) # clear back chain
.endm .endm
...@@ -179,12 +179,18 @@ system_call: ...@@ -179,12 +179,18 @@ system_call:
SAVE_ALL_BASE SAVE_ALL_BASE
SAVE_ALL __LC_SVC_OLD_PSW,1 SAVE_ALL __LC_SVC_OLD_PSW,1
lh %r7,0x8a # get svc number from lowcore lh %r7,0x8a # get svc number from lowcore
GET_THREAD_INFO # load pointer to task_struct to R9
sll %r7,2
stosm 24(%r15),0x03 # reenable interrupts stosm 24(%r15),0x03 # reenable interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
sla %r7,2 # *4 and test for svc 0
bnz BASED(sysc_do_restart) # svc number > 0
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(sysc_do_restart)
lr %r7,%r1 # copy svc number to %r7
sla %r7,2 # *4
sysc_do_restart: sysc_do_restart:
l %r8,sys_call_table-entry_base(%r7,%r13) # get system call addr.
tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE
l %r8,sys_call_table-entry_base(%r7,%r13) # get system call addr.
bo BASED(sysc_tracesys) bo BASED(sysc_tracesys)
basr %r14,%r8 # call sys_xxxx basr %r14,%r8 # call sys_xxxx
st %r2,SP_R2(%r15) # store return value (change R2 on stack) st %r2,SP_R2(%r15) # store return value (change R2 on stack)
...@@ -247,7 +253,7 @@ sysc_restart: ...@@ -247,7 +253,7 @@ sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
stosm 24(%r15),0x03 # reenable interrupts stosm 24(%r15),0x03 # reenable interrupts
l %r7,SP_R2(%r15) # load new svc number l %r7,SP_R2(%r15) # load new svc number
sll %r7,2 sla %r2,2
mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
lm %r2,%r6,SP_R2(%r15) # load svc arguments lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_restart) # restart svc b BASED(sysc_do_restart) # restart svc
...@@ -260,9 +266,10 @@ sysc_tracesys: ...@@ -260,9 +266,10 @@ sysc_tracesys:
srl %r7,2 srl %r7,2
st %r7,SP_R2(%r15) st %r7,SP_R2(%r15)
basr %r14,%r1 basr %r14,%r1
clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
bl BASED(sysc_tracego)
l %r7,SP_R2(%r15) # strace might have changed the l %r7,SP_R2(%r15) # strace might have changed the
n %r7,BASED(.Lc256) # system call sll %r7,2 # system call
sll %r7,2
l %r8,sys_call_table-entry_base(%r7,%r13) l %r8,sys_call_table-entry_base(%r7,%r13)
sysc_tracego: sysc_tracego:
lm %r3,%r6,SP_R3(%r15) lm %r3,%r6,SP_R3(%r15)
...@@ -617,9 +624,15 @@ sys_call_table: ...@@ -617,9 +624,15 @@ sys_call_table:
.long sys_epoll_wait .long sys_epoll_wait
.long sys_set_tid_address .long sys_set_tid_address
.long sys_fadvise64 .long sys_fadvise64
.rept 255-253 .long sys_timer_create
.long sys_ni_syscall .long sys_timer_settime /* 255 */
.endr .long sys_timer_gettime
.long sys_timer_getoverrun
.long sys_timer_delete
.long sys_clock_settime
.long sys_clock_gettime
.long sys_clock_getres
.long sys_clock_nanosleep
/* /*
* Program check handler routine * Program check handler routine
...@@ -694,12 +707,19 @@ pgm_per_only: ...@@ -694,12 +707,19 @@ pgm_per_only:
# #
pgm_svcper: pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,1 SAVE_ALL __LC_SVC_OLD_PSW,1
GET_THREAD_INFO # load pointer to task_struct to R9 lh %r7,0x8a # get svc number from lowcore
stosm 24(%r15),0x03 # reenable interrupts stosm 24(%r15),0x03 # reenable interrupts
lh %r8,0x8a # get svc number from lowcore GET_THREAD_INFO # load pointer to task_struct to R9
sll %r8,2 sla %r7,2 # *4 and test for svc 0
l %r8,sys_call_table-entry_base(%r8,%r13) # get system call addr. bnz BASED(pgm_svcstd) # svc number > 0 ?
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(pgm_svcstd)
lr %r7,%r1 # copy svc number to %r7
sla %r7,2 # *4
pgm_svcstd:
tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE
l %r8,sys_call_table-entry_base(%r7,%r13) # get system call addr.
bo BASED(pgm_tracesys) bo BASED(pgm_tracesys)
basr %r14,%r8 # call sys_xxxx basr %r14,%r8 # call sys_xxxx
st %r2,SP_R2(%r15) # store return value (change R2 on stack) st %r2,SP_R2(%r15) # store return value (change R2 on stack)
...@@ -725,13 +745,14 @@ pgm_svcper_nosig: ...@@ -725,13 +745,14 @@ pgm_svcper_nosig:
# #
pgm_tracesys: pgm_tracesys:
l %r1,BASED(.Ltrace) l %r1,BASED(.Ltrace)
mvc SP_R2(%r15),BASED(.Lc_ENOSYS) srl %r7,2
st %r7,SP_R2(%r15)
basr %r14,%r1 basr %r14,%r1
clc SP_R2(4,%r15),BASED(.Lc256) clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
bnl BASED(pgm_svc_go) bl BASED(pgm_svc_go)
l %r8,SP_R2(%r15) # strace changed the syscall l %r7,SP_R2(%r15) # strace changed the syscall
sll %r8,2 sll %r7,2
l %r8,sys_call_table-entry_base(%r8,%r13) l %r8,sys_call_table-entry_base(%r7,%r13)
pgm_svc_go: pgm_svc_go:
lm %r3,%r6,SP_R3(%r15) lm %r3,%r6,SP_R3(%r15)
l %r2,SP_ORIG_R2(%r15) l %r2,SP_ORIG_R2(%r15)
...@@ -922,7 +943,12 @@ restart_go: ...@@ -922,7 +943,12 @@ restart_go:
.Lc_ENOSYS: .long -ENOSYS .Lc_ENOSYS: .long -ENOSYS
.Lc_pactive: .long PREEMPT_ACTIVE .Lc_pactive: .long PREEMPT_ACTIVE
.Lc0xff: .long 0xff .Lc0xff: .long 0xff
.Lc256: .long 256 .Lnr_syscalls: .long NR_syscalls
.L0x018: .long 0x018
.L0x020: .long 0x020
.L0x028: .long 0x028
.L0x030: .long 0x030
.L0x038: .long 0x038
/* /*
* Symbol constants * Symbol constants
......
...@@ -249,130 +249,170 @@ ...@@ -249,130 +249,170 @@
#define __NR_epoll_wait 251 #define __NR_epoll_wait 251
#define __NR_set_tid_address 252 #define __NR_set_tid_address 252
#define __NR_fadvise64 253 #define __NR_fadvise64 253
#define __NR_timer_create 254
#define __NR_timer_settime (__NR_timer_create+1)
#define __NR_timer_gettime (__NR_timer_create+2)
#define __NR_timer_getoverrun (__NR_timer_create+3)
#define __NR_timer_delete (__NR_timer_create+4)
#define __NR_clock_settime (__NR_timer_create+5)
#define __NR_clock_gettime (__NR_timer_create+6)
#define __NR_clock_getres (__NR_timer_create+7)
#define __NR_clock_nanosleep (__NR_timer_create+8)
#define NR_syscalls 263
/* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */ /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
#define __syscall_return(type, res) \ #define __syscall_return(type, res) \
do { \ do { \
if ((unsigned long)(res) >= (unsigned long)(-125)) { \ if ((unsigned long)(res) >= (unsigned long)(-125)) { \
errno = -(res); \ errno = -(res); \
res = -1; \ res = -1; \
} \ } \
return (type) (res); \ return (type) (res); \
} while (0) } while (0)
#define _svc_clobber "cc", "memory" #define _svc_clobber "1", "cc", "memory"
#define _syscall0(type,name) \ #define _syscall0(type,name) \
type name(void) { \ type name(void) { \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" svc %b1\n" \ " .if %b1 < 256\n" \
: "=d" (__svcres) \ " svc %b1\n" \
: "i" (__NR_##name) \ " .else\n" \
: _svc_clobber ); \ " lhi %%r1,%b1\n" \
__res = __svcres; \ " svc 0\n" \
__syscall_return(type,__res); \ " .endif" \
: "=d" (__svcres) \
: "i" (__NR_##name) \
: _svc_clobber ); \
__res = __svcres; \
__syscall_return(type,__res); \
} }
#define _syscall1(type,name,type1,arg1) \ #define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) { \ type name(type1 arg1) { \
register type1 __arg1 asm("2") = arg1; \ register type1 __arg1 asm("2") = arg1; \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" svc %b1\n" \ " .if %b1 < 256\n" \
: "=d" (__svcres) \ " svc %b1\n" \
: "i" (__NR_##name), \ " .else\n" \
"0" (__arg1) \ " lhi %%r1,%b1\n" \
: _svc_clobber ); \ " svc 0\n" \
__res = __svcres; \ " .endif" \
__syscall_return(type,__res); \ : "=d" (__svcres) \
: "i" (__NR_##name), \
"0" (__arg1) \
: _svc_clobber ); \
__res = __svcres; \
__syscall_return(type,__res); \
} }
#define _syscall2(type,name,type1,arg1,type2,arg2) \ #define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1, type2 arg2) { \ type name(type1 arg1, type2 arg2) { \
register type1 __arg1 asm("2") = arg1; \ register type1 __arg1 asm("2") = arg1; \
register type2 __arg2 asm("3") = arg2; \ register type2 __arg2 asm("3") = arg2; \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" svc %b1\n" \ " .if %b1 < 256\n" \
: "=d" (__svcres) \ " svc %b1\n" \
: "i" (__NR_##name), \ " .else\n" \
"0" (__arg1), \ " lhi %%r1,%b1\n" \
"d" (__arg2) \ " svc 0\n" \
: _svc_clobber ); \ " .endif" \
__res = __svcres; \ : "=d" (__svcres) \
__syscall_return(type,__res); \ : "i" (__NR_##name), \
"0" (__arg1), \
"d" (__arg2) \
: _svc_clobber ); \
__res = __svcres; \
__syscall_return(type,__res); \
} }
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)\ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)\
type name(type1 arg1, type2 arg2, type3 arg3) { \ type name(type1 arg1, type2 arg2, type3 arg3) { \
register type1 __arg1 asm("2") = arg1; \ register type1 __arg1 asm("2") = arg1; \
register type2 __arg2 asm("3") = arg2; \ register type2 __arg2 asm("3") = arg2; \
register type3 __arg3 asm("4") = arg3; \ register type3 __arg3 asm("4") = arg3; \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" svc %b1\n" \ " .if %b1 < 256\n" \
: "=d" (__svcres) \ " svc %b1\n" \
: "i" (__NR_##name), \ " .else\n" \
"0" (__arg1), \ " lhi %%r1,%b1\n" \
"d" (__arg2), \ " svc 0\n" \
"d" (__arg3) \ " .endif" \
: _svc_clobber ); \ : "=d" (__svcres) \
__res = __svcres; \ : "i" (__NR_##name), \
__syscall_return(type,__res); \ "0" (__arg1), \
"d" (__arg2), \
"d" (__arg3) \
: _svc_clobber ); \
__res = __svcres; \
__syscall_return(type,__res); \
} }
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,\ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,\
type4,name4) \ type4,name4) \
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
register type1 __arg1 asm("2") = arg1; \ register type1 __arg1 asm("2") = arg1; \
register type2 __arg2 asm("3") = arg2; \ register type2 __arg2 asm("3") = arg2; \
register type3 __arg3 asm("4") = arg3; \ register type3 __arg3 asm("4") = arg3; \
register type4 __arg4 asm("5") = arg4; \ register type4 __arg4 asm("5") = arg4; \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" svc %b1\n" \ " .if %b1 < 256\n" \
: "=d" (__svcres) \ " svc %b1\n" \
: "i" (__NR_##name), \ " .else\n" \
"0" (__arg1), \ " lhi %%r1,%b1\n" \
"d" (__arg2), \ " svc 0\n" \
"d" (__arg3), \ " .endif" \
"d" (__arg4) \ : "=d" (__svcres) \
: _svc_clobber ); \ : "i" (__NR_##name), \
__res = __svcres; \ "0" (__arg1), \
__syscall_return(type,__res); \ "d" (__arg2), \
"d" (__arg3), \
"d" (__arg4) \
: _svc_clobber ); \
__res = __svcres; \
__syscall_return(type,__res); \
} }
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,\ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,\
type4,name4,type5,name5) \ type4,name4,type5,name5) \
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
type5 arg5) { \ type5 arg5) { \
register type1 __arg1 asm("2") = arg1; \ register type1 __arg1 asm("2") = arg1; \
register type2 __arg2 asm("3") = arg2; \ register type2 __arg2 asm("3") = arg2; \
register type3 __arg3 asm("4") = arg3; \ register type3 __arg3 asm("4") = arg3; \
register type4 __arg4 asm("5") = arg4; \ register type4 __arg4 asm("5") = arg4; \
register type5 __arg5 asm("6") = arg5; \ register type5 __arg5 asm("6") = arg5; \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" svc %b1\n" \ " .if %b1 < 256\n" \
: "=d" (__svcres) \ " svc %b1\n" \
: "i" (__NR_##name), \ " .else\n" \
"0" (__arg1), \ " lhi %%r1,%b1\n" \
"d" (__arg2), \ " svc 0\n" \
"d" (__arg3), \ " .endif" \
"d" (__arg4), \ : "=d" (__svcres) \
"d" (__arg5) \ : "i" (__NR_##name), \
: _svc_clobber ); \ "0" (__arg1), \
__res = __svcres; \ "d" (__arg2), \
__syscall_return(type,__res); \ "d" (__arg3), \
"d" (__arg4), \
"d" (__arg5) \
: _svc_clobber ); \
__res = __svcres; \
__syscall_return(type,__res); \
} }
#ifdef __KERNEL_SYSCALLS__ #ifdef __KERNEL_SYSCALLS__
......
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