From b18c1e47659b62647bf04f94bc3357aad26b8c73 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 25 Sep 2003 18:01:45 -0700 Subject: [PATCH] [PATCH] s390: system call restart bug. Fix restarting of system calls done by use of the execute instruction. --- arch/s390/kernel/compat_signal.c | 9 +++++++-- arch/s390/kernel/entry.S | 18 ++++++++++-------- arch/s390/kernel/entry64.S | 18 ++++++++++-------- arch/s390/kernel/signal.c | 4 ++-- include/asm-s390/ptrace.h | 3 ++- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index a128403e4d98a..a7e89edfb900a 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -579,7 +579,7 @@ handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, /* fallthrough */ case -ERESTARTNOINTR: regs->gprs[2] = regs->orig_gpr2; - regs->psw.addr -= 2; + regs->psw.addr -= regs->ilc; } } @@ -641,7 +641,12 @@ int do_signal32(struct pt_regs *regs, sigset_t *oldset) regs->gprs[2] == -ERESTARTSYS || regs->gprs[2] == -ERESTARTNOINTR) { regs->gprs[2] = regs->orig_gpr2; - regs->psw.addr -= 2; + regs->psw.addr -= regs->ilc; + } + /* Restart the system call with a new system call number */ + if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) { + regs->gprs[2] = __NR_restart_syscall; + set_thread_flag(TIF_RESTART_SVC); } } return 0; diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 5c2e6861c5c3b..79f75d3383efb 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -45,8 +45,9 @@ SP_R15 = STACK_FRAME_OVERHEAD + PT_GPR15 SP_AREGS = STACK_FRAME_OVERHEAD + PT_ACR0 SP_ORIG_R2 = STACK_FRAME_OVERHEAD + PT_ORIGGPR2 /* Now the additional entries */ -SP_TRAP = (SP_ORIG_R2+GPR_SIZE) -SP_SIZE = (SP_TRAP+4) +SP_ILC = (SP_ORIG_R2+GPR_SIZE) +SP_TRAP = (SP_ILC+2) +SP_SIZE = (SP_TRAP+2) _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC) _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) @@ -98,7 +99,8 @@ entry_base: 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_PSW(8,%r15),\psworg # move user PSW to stack - mvc SP_TRAP(4,%r15),BASED(.L\psworg) # store trap indication + mvc SP_ILC(2,%r15),__LC_SVC_ILC # store instruction length + mvc SP_TRAP(2,%r15),BASED(.L\psworg) # store trap indication xc 0(4,%r15),0(%r15) # clear back chain .endm @@ -670,11 +672,11 @@ restart_go: .Lc_pactive: .long PREEMPT_ACTIVE .Lc0xff: .long 0xff .Lnr_syscalls: .long NR_syscalls -.L0x018: .long 0x018 -.L0x020: .long 0x020 -.L0x028: .long 0x028 -.L0x030: .long 0x030 -.L0x038: .long 0x038 +.L0x018: .word 0x018 +.L0x020: .word 0x020 +.L0x028: .word 0x028 +.L0x030: .word 0x030 +.L0x038: .word 0x038 /* * Symbol constants diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 8140fdf2a9844..ebeec5dd46361 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -45,8 +45,9 @@ SP_R15 = STACK_FRAME_OVERHEAD + PT_GPR15 SP_AREGS = STACK_FRAME_OVERHEAD + PT_ACR0 SP_ORIG_R2 = STACK_FRAME_OVERHEAD + PT_ORIGGPR2 /* Now the additional entries */ -SP_TRAP = (SP_ORIG_R2+GPR_SIZE) -SP_SIZE = (SP_TRAP+4) +SP_ILC = (SP_ORIG_R2+GPR_SIZE) +SP_TRAP = (SP_ILC+2) +SP_SIZE = (SP_TRAP+2) _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC) _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) @@ -86,7 +87,8 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst. mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+16 # store ac. regs mvc SP_PSW(16,%r15),\psworg # move user PSW to stack - mvc SP_TRAP(4,%r15),.L\psworg-.Lconst(%r14) # store trap ind. + mvc SP_ILC(2,%r15),__LC_SVC_ILC # store instruction length + mvc SP_TRAP(2,%r15),.L\psworg-.Lconst(%r14) # store trap ind. xc 0(8,%r15),0(%r15) # clear back chain .endm @@ -690,9 +692,9 @@ restart_go: .Lconst: .Lc_ac: .long 0,0,1 .Lc_pactive: .long PREEMPT_ACTIVE -.L0x0130: .long 0x0130 -.L0x0140: .long 0x0140 -.L0x0150: .long 0x0150 -.L0x0160: .long 0x0160 -.L0x0170: .long 0x0170 +.L0x0130: .word 0x0130 +.L0x0140: .word 0x0140 +.L0x0150: .word 0x0150 +.L0x0160: .word 0x0160 +.L0x0170: .word 0x0170 .Lnr_syscalls: .long NR_syscalls diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index d162702ef6583..94696fca669db 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -418,7 +418,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, /* fallthrough */ case -ERESTARTNOINTR: regs->gprs[2] = regs->orig_gpr2; - regs->psw.addr -= 2; + regs->psw.addr -= regs->ilc; } } @@ -487,7 +487,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) regs->gprs[2] == -ERESTARTSYS || regs->gprs[2] == -ERESTARTNOINTR) { regs->gprs[2] = regs->orig_gpr2; - regs->psw.addr -= 2; + regs->psw.addr -= regs->ilc; } /* Restart the system call with a new system call number */ if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) { diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index 36d77a6fe7e0c..4169b15a9a992 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h @@ -301,7 +301,8 @@ struct pt_regs unsigned long gprs[NUM_GPRS]; unsigned int acrs[NUM_ACRS]; unsigned long orig_gpr2; - unsigned int trap; + unsigned short ilc; + unsigned short trap; } __attribute__ ((packed)); /* -- 2.53.0