Commit af25b8c4 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: nanosleep restarting.

sys_restart_syscall for nanosleep restarting.
parent 0e08b4bd
......@@ -47,7 +47,8 @@ SP_ORIG_R2 = STACK_FRAME_OVERHEAD + PT_ORIGGPR2
SP_TRAP = (SP_ORIG_R2+GPR_SIZE)
SP_SIZE = (SP_TRAP+4)
_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
/*
* Base Address of this Module --- saved in __LC_ENTRY_BASE
......@@ -181,6 +182,7 @@ system_call:
GET_THREAD_INFO # load pointer to task_struct to R9
sll %r7,2
stosm 24(%r15),0x03 # reenable interrupts
sysc_do_restart:
l %r8,sys_call_table-entry_base(%r7,%r13) # get system call addr.
tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE
bo BASED(sysc_tracesys)
......@@ -191,7 +193,7 @@ system_call:
sysc_return:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
sysc_leave:
RESTORE_ALL 1
......@@ -202,7 +204,7 @@ sysc_leave:
sysc_work_loop:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bz BASED(sysc_leave) # there is no work to do
#
# One of the work bits is on. Find out which one.
......@@ -213,6 +215,8 @@ sysc_work:
bo BASED(sysc_reschedule)
tm __TI_flags+3(%r9),_TIF_SIGPENDING
bo BASED(sysc_sigpending)
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
bo BASED(sysc_restart)
b BASED(sysc_leave)
#
......@@ -236,15 +240,27 @@ sysc_sigpending:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
b BASED(sysc_leave) # out of here, do NOT recheck
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
#
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
stosm 24(%r15),0x03 # reenable interrupts
l %r7,SP_R2(%r15) # load new svc number
sll %r7,2
mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_restart) # restart svc
#
# call trace before and after sys_call
#
sysc_tracesys:
l %r1,BASED(.Ltrace)
srl %r7,2
st %r7,SP_R2(4,%r15)
st %r7,SP_R2(%r15)
basr %r14,%r1
l %r7,SP_R2(4,%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
l %r8,sys_call_table-entry_base(%r7,%r13)
......@@ -354,7 +370,7 @@ sys_call_table:
.long sys_write
.long sys_open /* 5 */
.long sys_close
.long sys_ni_syscall /* old waitpid syscall holder */
.long sys_restart_syscall
.long sys_creat
.long sys_link
.long sys_unlink /* 10 */
......@@ -752,7 +768,7 @@ io_return:
#else
bno BASED(io_leave) # no-> skip resched & signal
#endif
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_INT
bnz BASED(io_work) # there is work to do (signals etc.)
io_leave:
RESTORE_ALL 0
......@@ -788,7 +804,7 @@ io_resume_loop:
io_work_loop:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_INT
bz BASED(io_leave) # there is no work to do
#
# One of the work bits is on. Find out which one.
......
......@@ -397,6 +397,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */
switch (regs->gprs[2]) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn =
do_no_restart_syscall;
clear_thread_flag(TIF_RESTART_SVC);
case -ERESTARTNOHAND:
regs->gprs[2] = -EINTR;
break;
......@@ -473,6 +477,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr -= 2;
}
/* 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;
}
......@@ -47,7 +47,8 @@ SP_ORIG_R2 = STACK_FRAME_OVERHEAD + PT_ORIGGPR2
SP_TRAP = (SP_ORIG_R2+GPR_SIZE)
SP_SIZE = (SP_TRAP+4)
_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
/*
* Register usage in interrupt handlers:
......@@ -161,6 +162,7 @@ system_call:
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
GET_THREAD_INFO # load pointer to task_struct to R9
stosm 48(%r15),0x03 # reenable interrupts
sysc_do_restart:
larl %r10,sys_call_table
sll %r7,3
tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ?
......@@ -177,7 +179,7 @@ sysc_noemu:
sysc_return:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.)
sysc_leave:
RESTORE_ALL 1
......@@ -188,7 +190,7 @@ sysc_leave:
sysc_work_loop:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jz sysc_leave # there is no work to do
#
# One of the work bits is on. Find out which one.
......@@ -199,6 +201,8 @@ sysc_work:
jo sysc_reschedule
tm __TI_flags+7(%r9),_TIF_SIGPENDING
jo sysc_sigpending
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
jo sysc_restart
j sysc_leave
#
......@@ -220,6 +224,17 @@ sysc_sigpending:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
j sysc_leave # out of here, do NOT recheck
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
#
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
stosm 48(%r15),0x03 # reenable interrupts
lg %r7,SP_R2(%r15) # load new svc number
mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
lmg %r2,%r6,SP_R2(%r15) # load svc arguments
j sysc_do_restart # restart svc
#
# call syscall_trace before and after system call
# special linkage: %r12 contains the return address for trace_svc
......@@ -383,7 +398,7 @@ sys_call_table:
.long SYSCALL(sys_write,sys32_write_wrapper)
.long SYSCALL(sys_open,sys32_open_wrapper) /* 5 */
.long SYSCALL(sys_close,sys32_close_wrapper)
.long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old waitpid syscall */
.long SYSCALL(sys_restart_syscall,sys_ni_syscall)
.long SYSCALL(sys_creat,sys32_creat_wrapper)
.long SYSCALL(sys_link,sys32_link_wrapper)
.long SYSCALL(sys_unlink,sys32_unlink_wrapper) /* 10 */
......@@ -777,7 +792,7 @@ io_return:
#else
jno io_leave # no-> skip resched & signal
#endif
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_INT
jnz io_work # there is work to do (signals etc.)
io_leave:
RESTORE_ALL 0
......@@ -813,7 +828,7 @@ io_resume_loop:
io_work_loop:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_INT
jz io_leave # there is no work to do
#
# One of the work bits is on. Find out which one.
......
......@@ -391,6 +391,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */
switch (regs->gprs[2]) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn =
do_no_restart_syscall;
clear_thread_flag(TIF_RESTART_SVC);
case -ERESTARTNOHAND:
regs->gprs[2] = -EINTR;
break;
......@@ -473,6 +477,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr -= 2;
}
/* 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;
}
......@@ -13,7 +13,7 @@
#ifdef __KERNEL__
#include <asm/thread_info.h>
#include <linux/thread_info.h>
struct task_struct;
......
......@@ -26,6 +26,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
unsigned int preempt_count; /* 0 => preemptable */
struct restart_block restart_block;
};
/*
......@@ -33,10 +34,13 @@ struct thread_info {
*/
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
exec_domain: &default_exec_domain, \
flags: 0, \
cpu: 0, \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}
#define init_thread_info (init_thread_union.thread_info)
......@@ -69,6 +73,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
......@@ -77,6 +82,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
......
......@@ -19,6 +19,7 @@
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_restart_syscall 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
......
......@@ -13,7 +13,7 @@
#ifdef __KERNEL__
#include <asm/thread_info.h>
#include <linux/thread_info.h>
struct task_struct;
......
......@@ -26,6 +26,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
unsigned int preempt_count; /* 0 => preemptable */
struct restart_block restart_block;
};
/*
......@@ -33,10 +34,13 @@ struct thread_info {
*/
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
exec_domain: &default_exec_domain, \
flags: 0, \
cpu: 0, \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}
#define init_thread_info (init_thread_union.thread_info)
......@@ -69,6 +73,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
......@@ -77,6 +82,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
......
......@@ -19,6 +19,7 @@
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_restart_syscall 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
......
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