From: Martin Schwidefsky 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: Martin Schwidefsky Signed-off-by: Andrew Morton --- 25-akpm/arch/s390/kernel/asm-offsets.c | 1 + 25-akpm/arch/s390/kernel/compat_wrapper.S | 2 ++ 25-akpm/arch/s390/kernel/entry.S | 10 +++++++--- 25-akpm/arch/s390/kernel/entry64.S | 10 +++++++--- 25-akpm/arch/s390/kernel/ptrace.c | 10 +++++----- 25-akpm/include/asm-s390/ptrace.h | 1 + 6 files changed, 23 insertions(+), 11 deletions(-) diff -puN arch/s390/kernel/asm-offsets.c~s390-add-support-for-6-system-call-arguments arch/s390/kernel/asm-offsets.c --- 25/arch/s390/kernel/asm-offsets.c~s390-add-support-for-6-system-call-arguments 2004-06-07 22:06:52.869018800 -0700 +++ 25-akpm/arch/s390/kernel/asm-offsets.c 2004-06-07 22:06:52.886016216 -0700 @@ -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),); diff -puN arch/s390/kernel/compat_wrapper.S~s390-add-support-for-6-system-call-arguments arch/s390/kernel/compat_wrapper.S --- 25/arch/s390/kernel/compat_wrapper.S~s390-add-support-for-6-system-call-arguments 2004-06-07 22:06:52.870018648 -0700 +++ 25-akpm/arch/s390/kernel/compat_wrapper.S 2004-06-07 22:06:52.887016064 -0700 @@ -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 diff -puN arch/s390/kernel/entry64.S~s390-add-support-for-6-system-call-arguments arch/s390/kernel/entry64.S --- 25/arch/s390/kernel/entry64.S~s390-add-support-for-6-system-call-arguments 2004-06-07 22:06:52.872018344 -0700 +++ 25-akpm/arch/s390/kernel/entry64.S 2004-06-07 22:06:52.888015912 -0700 @@ -24,7 +24,8 @@ * Stack layout for the system_call stack entry. * The first few entries are identical to the user_regs_struct. */ -SP_PTREGS = STACK_FRAME_OVERHEAD +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 ? diff -puN arch/s390/kernel/entry.S~s390-add-support-for-6-system-call-arguments arch/s390/kernel/entry.S --- 25/arch/s390/kernel/entry.S~s390-add-support-for-6-system-call-arguments 2004-06-07 22:06:52.880017128 -0700 +++ 25-akpm/arch/s390/kernel/entry.S 2004-06-07 22:06:52.888015912 -0700 @@ -24,7 +24,8 @@ * Stack layout for the system_call stack entry. * The first few entries are identical to the user_regs_struct. */ -SP_PTREGS = STACK_FRAME_OVERHEAD +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) diff -puN arch/s390/kernel/ptrace.c~s390-add-support-for-6-system-call-arguments arch/s390/kernel/ptrace.c --- 25/arch/s390/kernel/ptrace.c~s390-add-support-for-6-system-call-arguments 2004-06-07 22:06:52.881016976 -0700 +++ 25-akpm/arch/s390/kernel/ptrace.c 2004-06-07 22:06:52.889015760 -0700 @@ -141,7 +141,7 @@ peek_user(struct task_struct *child, add /* * 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, add 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 *chil 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 *chil (__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)) { /* diff -puN include/asm-s390/ptrace.h~s390-add-support-for-6-system-call-arguments include/asm-s390/ptrace.h --- 25/include/asm-s390/ptrace.h~s390-add-support-for-6-system-call-arguments 2004-06-07 22:06:52.882016824 -0700 +++ 25-akpm/include/asm-s390/ptrace.h 2004-06-07 22:06:52.890015608 -0700 @@ -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; _