sys_restart_syscall for nanosleep restarting.
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
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)
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
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.
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)
#
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)
.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 */
#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
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.
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;
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;
}
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:
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 ?
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
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.
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
#
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
.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 */
#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
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.
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;
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;
}
#ifdef __KERNEL__
-#include <asm/thread_info.h>
+#include <linux/thread_info.h>
struct task_struct;
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
unsigned int preempt_count; /* 0 => preemptable */
+ struct restart_block restart_block;
};
/*
*/
#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)
#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 */
#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)
#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
#ifdef __KERNEL__
-#include <asm/thread_info.h>
+#include <linux/thread_info.h>
struct task_struct;
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
unsigned int preempt_count; /* 0 => preemptable */
+ struct restart_block restart_block;
};
/*
*/
#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)
#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 */
#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)
#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