Commit f1b2f7ff authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: add support for 6 system call arguments (FUTEX_CMP_REQUEUE)

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

This patch adds support for 6 system call arguments on s390.  The first
exploiter of this will be the sys_futex system call for the
FUTEX_CMP_REQUEUE operation.  The idea is simple: use register %r7 for the
6th argument.  This can be extended to 7/8/9/...  arguments if there ever
will be the need for it.  To call the system call function in the kernel
the additional arguments needs to get stored on the stack.  8 bytes are
added to the head of struct pt_regs.  %r7 is stored to the additional field
for all system calls.  The store is hidden in a
address-generation-interlock slot, it doesn't slow down the system call
path.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a57867c3
......@@ -32,6 +32,7 @@ int main(void)
DEFINE(__TI_cpu, offsetof(struct thread_info, cpu),);
DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count),);
BLANK();
DEFINE(__PT_ARGS, offsetof(struct pt_regs, args),);
DEFINE(__PT_PSW, offsetof(struct pt_regs, psw),);
DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs),);
DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2),);
......
......@@ -1097,6 +1097,8 @@ compat_sys_futex_wrapper:
lgfr %r4,%r4 # int
llgtr %r5,%r5 # struct compat_timespec *
llgtr %r6,%r6 # u32 *
lgf %r0,164(%r15) # int
stg %r0,160(%r15)
jg compat_sys_futex # branch to system call
.globl sys32_setxattr_wrapper
......
......@@ -25,6 +25,7 @@
* The first few entries are identical to the user_regs_struct.
*/
SP_PTREGS = STACK_FRAME_OVERHEAD
SP_ARGS = STACK_FRAME_OVERHEAD + __PT_ARGS
SP_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
SP_R0 = STACK_FRAME_OVERHEAD + __PT_GPRS
SP_R1 = STACK_FRAME_OVERHEAD + __PT_GPRS + 4
......@@ -230,12 +231,14 @@ system_call:
sysc_enter:
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
bnz BASED(sysc_nr_ok) # svc number > 0
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(sysc_do_restart)
bnl BASED(sysc_nr_ok)
lr %r7,%r1 # copy svc number to %r7
sla %r7,2 # *4
sysc_nr_ok:
mvc SP_ARGS(4,%r15),SP_R7(%r15)
sysc_do_restart:
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
l %r8,sys_call_table-system_call(%r7,%r13) # get system call addr.
......@@ -510,6 +513,7 @@ pgm_svcper:
lr %r7,%r1 # copy svc number to %r7
sla %r7,2 # *4
pgm_svcstd:
mvc SP_ARGS(4,%r15),SP_R7(%r15)
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
l %r8,sys_call_table-system_call(%r7,%r13) # get system call addr.
bnz BASED(pgm_tracesys)
......
......@@ -25,6 +25,7 @@
* The first few entries are identical to the user_regs_struct.
*/
SP_PTREGS = STACK_FRAME_OVERHEAD
SP_ARGS = STACK_FRAME_OVERHEAD + __PT_ARGS
SP_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
SP_R0 = STACK_FRAME_OVERHEAD + __PT_GPRS
SP_R1 = STACK_FRAME_OVERHEAD + __PT_GPRS + 8
......@@ -214,13 +215,15 @@ system_call:
sysc_enter:
GET_THREAD_INFO # load pointer to task_struct to R9
slag %r7,%r7,2 # *4 and test for svc 0
jnz sysc_do_restart
jnz sysc_nr_ok
# svc 0: system call number in %r1
lghi %r0,NR_syscalls
clr %r1,%r0
jnl sysc_do_restart
jnl sysc_nr_ok
lgfr %r7,%r1 # clear high word in r1
slag %r7,%r7,2 # svc 0: system call number in %r1
sysc_nr_ok:
mvc SP_ARGS(8,%r15),SP_R7(%r15)
sysc_do_restart:
larl %r10,sys_call_table
#ifdef CONFIG_S390_SUPPORT
......@@ -542,6 +545,7 @@ pgm_svcper:
clr %r1,%r0
slag %r7,%r1,2
pgm_svcstd:
mvc SP_ARGS(8,%r15),SP_R7(%r15)
larl %r10,sys_call_table
#ifdef CONFIG_S390_SUPPORT
tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ?
......
......@@ -141,7 +141,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
/*
* psw and gprs are stored on the stack
*/
tmp = *(addr_t *)((addr_t) __KSTK_PTREGS(child) + addr);
tmp = *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr);
if (addr == (addr_t) &dummy->regs.psw.mask)
/* Remove per bit from user psw. */
tmp &= ~PSW_MASK_PER;
......@@ -215,7 +215,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
high order bit but older gdb's rely on it */
data |= PSW_ADDR_AMODE;
#endif
*(addr_t *)((addr_t) __KSTK_PTREGS(child) + addr) = data;
*(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr) = data;
} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
/*
......@@ -360,7 +360,7 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
PSW32_ADDR_AMODE31;
} else {
/* gpr 0-15 */
tmp = *(__u32 *)((addr_t) __KSTK_PTREGS(child) +
tmp = *(__u32 *)((addr_t) &__KSTK_PTREGS(child)->psw +
addr*2 + 4);
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
......@@ -439,8 +439,8 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
(__u64) tmp & PSW32_ADDR_INSN;
} else {
/* gpr 0-15 */
*(__u32*)((addr_t) __KSTK_PTREGS(child) + addr*2 + 4) =
tmp;
*(__u32*)((addr_t) &__KSTK_PTREGS(child)->psw
+ addr*2 + 4) = tmp;
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/*
......
......@@ -303,6 +303,7 @@ typedef struct
*/
struct pt_regs
{
unsigned long args[1];
psw_t psw;
unsigned long gprs[NUM_GPRS];
unsigned long orig_gpr2;
......
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