Commit 4a177cbf authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Tony Luck

[IA64] Add TIF_RESTORE_SIGMASK

Preparation for pselect and ppoll.
ia32 compat code not tested. :-(
Signed-off-by: default avatarAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: default avatarAlexey Dobriyan <adobriyan@openvz.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 690def21
...@@ -52,43 +52,6 @@ ENTRY(ia32_clone) ...@@ -52,43 +52,6 @@ ENTRY(ia32_clone)
br.ret.sptk.many rp br.ret.sptk.many rp
END(ia32_clone) END(ia32_clone)
ENTRY(sys32_rt_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
mov loc0=rp
mov out0=in0 // mask
mov out1=in1 // sigsetsize
mov out2=sp // out2 = &sigscratch
.fframe 16
adds sp=-16,sp // allocate dummy "sigscratch"
;;
.body
br.call.sptk.many rp=ia32_rt_sigsuspend
1: .restore sp
adds sp=16,sp
mov rp=loc0
mov ar.pfs=loc1
br.ret.sptk.many rp
END(sys32_rt_sigsuspend)
ENTRY(sys32_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
mov loc0=rp
mov out0=in2 // mask (first two args are ignored)
;;
mov out1=sp // out1 = &sigscratch
.fframe 16
adds sp=-16,sp // allocate dummy "sigscratch"
.body
br.call.sptk.many rp=ia32_sigsuspend
1: .restore sp
adds sp=16,sp
mov rp=loc0
mov ar.pfs=loc1
br.ret.sptk.many rp
END(sys32_sigsuspend)
GLOBAL_ENTRY(ia32_ret_from_clone) GLOBAL_ENTRY(ia32_ret_from_clone)
PT_REGS_UNWIND_INFO(0) PT_REGS_UNWIND_INFO(0)
{ /* { /*
...@@ -389,7 +352,7 @@ ia32_syscall_table: ...@@ -389,7 +352,7 @@ ia32_syscall_table:
data8 sys_rt_sigpending data8 sys_rt_sigpending
data8 compat_sys_rt_sigtimedwait data8 compat_sys_rt_sigtimedwait
data8 sys32_rt_sigqueueinfo data8 sys32_rt_sigqueueinfo
data8 sys32_rt_sigsuspend data8 compat_sys_rt_sigsuspend
data8 sys32_pread /* 180 */ data8 sys32_pread /* 180 */
data8 sys32_pwrite data8 sys32_pwrite
data8 sys_chown /* 16-bit version */ data8 sys_chown /* 16-bit version */
......
...@@ -452,59 +452,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r ...@@ -452,59 +452,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r
sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
} }
long asmlinkage long
__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) sys32_sigsuspend (int history0, int history1, old_sigset_t mask)
{ {
extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); mask &= _BLOCKABLE;
sigset_t oldset, set;
scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */
memset(&set, 0, sizeof(set));
memcpy(&set.sig, &sset->sig, sigsetsize);
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
{ current->saved_sigmask = current->blocked;
oldset = current->blocked; siginitset(&current->blocked, mask);
current->blocked = set; recalc_sigpending();
recalc_sigpending();
}
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
/* current->state = TASK_INTERRUPTIBLE;
* The return below usually returns to the signal handler. We need to pre-set the schedule();
* correct error code here to ensure that the right values get saved in sigcontext set_thread_flag(TIF_RESTORE_SIGMASK);
* by ia64_do_signal. return -ERESTARTNOHAND;
*/
scr->pt.r8 = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (ia64_do_signal(&oldset, scr, 1))
return -EINTR;
}
}
asmlinkage long
ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
{
compat_sigset_t set;
if (sigsetsize > sizeof(compat_sigset_t))
return -EINVAL;
if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
return -EFAULT;
return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
}
asmlinkage long
ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
{
return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
} }
asmlinkage long asmlinkage long
......
...@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user) ...@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user)
br.ret.sptk.many rp br.ret.sptk.many rp
END(notify_resume_user) END(notify_resume_user)
GLOBAL_ENTRY(sys_rt_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
mov r9=ar.unat
mov loc0=rp // save return address
mov out0=in0 // mask
mov out1=in1 // sigsetsize
adds out2=8,sp // out2=&sigscratch->ar_pfs
;;
.fframe 16
.spillsp ar.unat, 16
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
br.call.sptk.many rp=ia64_rt_sigsuspend
.ret17: .restore sp
adds sp=16,sp // pop scratch stack space
;;
ld8 r9=[sp] // load new unat from sw->caller_unat
mov rp=loc0
;;
mov ar.unat=r9
mov ar.pfs=loc1
br.ret.sptk.many rp
END(sys_rt_sigsuspend)
ENTRY(sys_rt_sigreturn) ENTRY(sys_rt_sigreturn)
PT_REGS_UNWIND_INFO(0) PT_REGS_UNWIND_INFO(0)
/* /*
......
...@@ -156,7 +156,7 @@ show_regs (struct pt_regs *regs) ...@@ -156,7 +156,7 @@ show_regs (struct pt_regs *regs)
} }
void void
do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
{ {
if (fsys_mode(current, &scr->pt)) { if (fsys_mode(current, &scr->pt)) {
/* defer signal-handling etc. until we return to privilege-level 0. */ /* defer signal-handling etc. until we return to privilege-level 0. */
...@@ -171,8 +171,8 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall ...@@ -171,8 +171,8 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall
#endif #endif
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (test_thread_flag(TIF_SIGPENDING)) if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
ia64_do_signal(oldset, scr, in_syscall); ia64_do_signal(scr, in_syscall);
} }
static int pal_halt = 1; static int pal_halt = 1;
......
...@@ -22,4 +22,4 @@ struct sigframe { ...@@ -22,4 +22,4 @@ struct sigframe {
struct sigcontext sc; struct sigcontext sc;
}; };
extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); extern void ia64_do_signal (struct sigscratch *, long);
...@@ -41,47 +41,6 @@ ...@@ -41,47 +41,6 @@
# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
#endif #endif
long
ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
{
sigset_t oldset, set;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (!access_ok(VERIFY_READ, uset, sigsetsize))
return -EFAULT;
if (GET_SIGSET(&set, uset))
return -EFAULT;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
{
oldset = current->blocked;
current->blocked = set;
recalc_sigpending();
}
spin_unlock_irq(&current->sighand->siglock);
/*
* The return below usually returns to the signal handler. We need to
* pre-set the correct error code here to ensure that the right values
* get saved in sigcontext by ia64_do_signal.
*/
scr->pt.r8 = EINTR;
scr->pt.r10 = -1;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (ia64_do_signal(&oldset, scr, 1))
return -EINTR;
}
}
asmlinkage long asmlinkage long
sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2,
long arg3, long arg4, long arg5, long arg6, long arg7, long arg3, long arg4, long arg5, long arg6, long arg7,
...@@ -478,10 +437,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse ...@@ -478,10 +437,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
* Note that `init' is a special process: it doesn't get signals it doesn't want to * Note that `init' is a special process: it doesn't get signals it doesn't want to
* handle. Thus you cannot kill init even with a SIGKILL even by mistake. * handle. Thus you cannot kill init even with a SIGKILL even by mistake.
*/ */
long void
ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) ia64_do_signal (struct sigscratch *scr, long in_syscall)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
long restart = in_syscall; long restart = in_syscall;
long errno = scr->pt.r8; long errno = scr->pt.r8;
...@@ -493,9 +453,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) ...@@ -493,9 +453,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
* doing anything if so. * doing anything if so.
*/ */
if (!user_mode(&scr->pt)) if (!user_mode(&scr->pt))
return 0; return;
if (!oldset) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->blocked;
/* /*
...@@ -558,8 +520,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) ...@@ -558,8 +520,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to * Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV... * continue to iterate in this loop so we can deliver the SIGSEGV...
*/ */
if (handle_signal(signr, &ka, &info, oldset, scr)) if (handle_signal(signr, &ka, &info, oldset, scr)) {
return 1; /* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
...@@ -585,5 +554,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) ...@@ -585,5 +554,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
} }
} }
} }
return 0;
/* if there's no signal to deliver, we just put the saved sigmask
* back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
...@@ -85,6 +85,7 @@ struct thread_info { ...@@ -85,6 +85,7 @@ struct thread_info {
#define TIF_SYSCALL_TRACE 3 /* syscall trace active */ #define TIF_SYSCALL_TRACE 3 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */
#define TIF_SINGLESTEP 5 /* restore singlestep on return to user mode */ #define TIF_SINGLESTEP 5 /* restore singlestep on return to user mode */
#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 #define TIF_MEMDIE 17
#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
...@@ -96,6 +97,7 @@ struct thread_info { ...@@ -96,6 +97,7 @@ struct thread_info {
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP) #define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
...@@ -104,7 +106,7 @@ struct thread_info { ...@@ -104,7 +106,7 @@ struct thread_info {
#define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_FREEZE (1 << TIF_FREEZE)
/* "work to do on user-return" bits */ /* "work to do on user-return" bits */
#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) #define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_RESTORE_SIGMASK)
/* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */ /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
#define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)) #define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
......
...@@ -300,6 +300,7 @@ ...@@ -300,6 +300,7 @@
#define NR_syscalls 281 /* length of syscall table */ #define NR_syscalls 281 /* length of syscall table */
#define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#ifdef CONFIG_IA32_SUPPORT #ifdef CONFIG_IA32_SUPPORT
# define __ARCH_WANT_SYS_FADVISE64 # define __ARCH_WANT_SYS_FADVISE64
...@@ -310,6 +311,7 @@ ...@@ -310,6 +311,7 @@
# define __ARCH_WANT_SYS_OLDUMOUNT # define __ARCH_WANT_SYS_OLDUMOUNT
# define __ARCH_WANT_SYS_SIGPENDING # define __ARCH_WANT_SYS_SIGPENDING
# define __ARCH_WANT_SYS_SIGPROCMASK # define __ARCH_WANT_SYS_SIGPROCMASK
# define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
# define __ARCH_WANT_COMPAT_SYS_TIME # define __ARCH_WANT_COMPAT_SYS_TIME
#endif #endif
......
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