aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@openvz.org>2007-01-23 11:03:17 -0500
committerTony Luck <tony.luck@intel.com>2007-05-08 17:51:59 -0400
commit4a177cbf84f827cf9f1d6cfa5264fafd3cc33ce0 (patch)
treeef04ada4e2b708ee965081cd905026c9156863d3 /arch
parent690def21414fa43fac1b8053fd952c0366c476de (diff)
[IA64] Add TIF_RESTORE_SIGMASK
Preparation for pselect and ppoll. ia32 compat code not tested. :-( Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Signed-off-by: Alexey Dobriyan <adobriyan@openvz.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/ia32/ia32_entry.S39
-rw-r--r--arch/ia64/ia32/ia32_signal.c59
-rw-r--r--arch/ia64/kernel/entry.S26
-rw-r--r--arch/ia64/kernel/process.c6
-rw-r--r--arch/ia64/kernel/sigframe.h2
-rw-r--r--arch/ia64/kernel/signal.c71
6 files changed, 38 insertions, 165 deletions
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 687e5fdc9683..99b665e2b1d5 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -52,43 +52,6 @@ ENTRY(ia32_clone)
52 br.ret.sptk.many rp 52 br.ret.sptk.many rp
53END(ia32_clone) 53END(ia32_clone)
54 54
55ENTRY(sys32_rt_sigsuspend)
56 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
57 alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
58 mov loc0=rp
59 mov out0=in0 // mask
60 mov out1=in1 // sigsetsize
61 mov out2=sp // out2 = &sigscratch
62 .fframe 16
63 adds sp=-16,sp // allocate dummy "sigscratch"
64 ;;
65 .body
66 br.call.sptk.many rp=ia32_rt_sigsuspend
671: .restore sp
68 adds sp=16,sp
69 mov rp=loc0
70 mov ar.pfs=loc1
71 br.ret.sptk.many rp
72END(sys32_rt_sigsuspend)
73
74ENTRY(sys32_sigsuspend)
75 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
76 alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
77 mov loc0=rp
78 mov out0=in2 // mask (first two args are ignored)
79 ;;
80 mov out1=sp // out1 = &sigscratch
81 .fframe 16
82 adds sp=-16,sp // allocate dummy "sigscratch"
83 .body
84 br.call.sptk.many rp=ia32_sigsuspend
851: .restore sp
86 adds sp=16,sp
87 mov rp=loc0
88 mov ar.pfs=loc1
89 br.ret.sptk.many rp
90END(sys32_sigsuspend)
91
92GLOBAL_ENTRY(ia32_ret_from_clone) 55GLOBAL_ENTRY(ia32_ret_from_clone)
93 PT_REGS_UNWIND_INFO(0) 56 PT_REGS_UNWIND_INFO(0)
94{ /* 57{ /*
@@ -389,7 +352,7 @@ ia32_syscall_table:
389 data8 sys_rt_sigpending 352 data8 sys_rt_sigpending
390 data8 compat_sys_rt_sigtimedwait 353 data8 compat_sys_rt_sigtimedwait
391 data8 sys32_rt_sigqueueinfo 354 data8 sys32_rt_sigqueueinfo
392 data8 sys32_rt_sigsuspend 355 data8 compat_sys_rt_sigsuspend
393 data8 sys32_pread /* 180 */ 356 data8 sys32_pread /* 180 */
394 data8 sys32_pwrite 357 data8 sys32_pwrite
395 data8 sys_chown /* 16-bit version */ 358 data8 sys_chown /* 16-bit version */
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 7b38b73e7827..b2bb7f227920 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -452,59 +452,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r
452 sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); 452 sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
453} 453}
454 454
455long 455asmlinkage long
456__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) 456sys32_sigsuspend (int history0, int history1, old_sigset_t mask)
457{ 457{
458 extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); 458 mask &= _BLOCKABLE;
459 sigset_t oldset, set;
460
461 scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */
462 memset(&set, 0, sizeof(set));
463
464 memcpy(&set.sig, &sset->sig, sigsetsize);
465
466 sigdelsetmask(&set, ~_BLOCKABLE);
467
468 spin_lock_irq(&current->sighand->siglock); 459 spin_lock_irq(&current->sighand->siglock);
469 { 460 current->saved_sigmask = current->blocked;
470 oldset = current->blocked; 461 siginitset(&current->blocked, mask);
471 current->blocked = set; 462 recalc_sigpending();
472 recalc_sigpending();
473 }
474 spin_unlock_irq(&current->sighand->siglock); 463 spin_unlock_irq(&current->sighand->siglock);
475 464
476 /* 465 current->state = TASK_INTERRUPTIBLE;
477 * The return below usually returns to the signal handler. We need to pre-set the 466 schedule();
478 * correct error code here to ensure that the right values get saved in sigcontext 467 set_thread_flag(TIF_RESTORE_SIGMASK);
479 * by ia64_do_signal. 468 return -ERESTARTNOHAND;
480 */
481 scr->pt.r8 = -EINTR;
482 while (1) {
483 current->state = TASK_INTERRUPTIBLE;
484 schedule();
485 if (ia64_do_signal(&oldset, scr, 1))
486 return -EINTR;
487 }
488}
489
490asmlinkage long
491ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
492{
493 compat_sigset_t set;
494
495 if (sigsetsize > sizeof(compat_sigset_t))
496 return -EINVAL;
497
498 if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
499 return -EFAULT;
500
501 return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
502}
503
504asmlinkage long
505ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
506{
507 return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
508} 469}
509 470
510asmlinkage long 471asmlinkage long
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 55fd2d5471e1..156a6fa031f4 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user)
1199 br.ret.sptk.many rp 1199 br.ret.sptk.many rp
1200END(notify_resume_user) 1200END(notify_resume_user)
1201 1201
1202GLOBAL_ENTRY(sys_rt_sigsuspend)
1203 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
1204 alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
1205 mov r9=ar.unat
1206 mov loc0=rp // save return address
1207 mov out0=in0 // mask
1208 mov out1=in1 // sigsetsize
1209 adds out2=8,sp // out2=&sigscratch->ar_pfs
1210 ;;
1211 .fframe 16
1212 .spillsp ar.unat, 16
1213 st8 [sp]=r9,-16 // allocate space for ar.unat and save it
1214 st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
1215 .body
1216 br.call.sptk.many rp=ia64_rt_sigsuspend
1217.ret17: .restore sp
1218 adds sp=16,sp // pop scratch stack space
1219 ;;
1220 ld8 r9=[sp] // load new unat from sw->caller_unat
1221 mov rp=loc0
1222 ;;
1223 mov ar.unat=r9
1224 mov ar.pfs=loc1
1225 br.ret.sptk.many rp
1226END(sys_rt_sigsuspend)
1227
1228ENTRY(sys_rt_sigreturn) 1202ENTRY(sys_rt_sigreturn)
1229 PT_REGS_UNWIND_INFO(0) 1203 PT_REGS_UNWIND_INFO(0)
1230 /* 1204 /*
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index cba6ac398736..d7b7d3da1ebb 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -156,7 +156,7 @@ show_regs (struct pt_regs *regs)
156} 156}
157 157
158void 158void
159do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) 159do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
160{ 160{
161 if (fsys_mode(current, &scr->pt)) { 161 if (fsys_mode(current, &scr->pt)) {
162 /* defer signal-handling etc. until we return to privilege-level 0. */ 162 /* 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#endif 171#endif
172 172
173 /* deal with pending signal delivery */ 173 /* deal with pending signal delivery */
174 if (test_thread_flag(TIF_SIGPENDING)) 174 if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
175 ia64_do_signal(oldset, scr, in_syscall); 175 ia64_do_signal(scr, in_syscall);
176} 176}
177 177
178static int pal_halt = 1; 178static int pal_halt = 1;
diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
index 37b986cb86e0..9fd9a1933b3d 100644
--- a/arch/ia64/kernel/sigframe.h
+++ b/arch/ia64/kernel/sigframe.h
@@ -22,4 +22,4 @@ struct sigframe {
22 struct sigcontext sc; 22 struct sigcontext sc;
23}; 23};
24 24
25extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); 25extern void ia64_do_signal (struct sigscratch *, long);
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 77f8b49c7882..034b81d62bb1 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -41,47 +41,6 @@
41# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) 41# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
42#endif 42#endif
43 43
44long
45ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
46{
47 sigset_t oldset, set;
48
49 /* XXX: Don't preclude handling different sized sigset_t's. */
50 if (sigsetsize != sizeof(sigset_t))
51 return -EINVAL;
52
53 if (!access_ok(VERIFY_READ, uset, sigsetsize))
54 return -EFAULT;
55
56 if (GET_SIGSET(&set, uset))
57 return -EFAULT;
58
59 sigdelsetmask(&set, ~_BLOCKABLE);
60
61 spin_lock_irq(&current->sighand->siglock);
62 {
63 oldset = current->blocked;
64 current->blocked = set;
65 recalc_sigpending();
66 }
67 spin_unlock_irq(&current->sighand->siglock);
68
69 /*
70 * The return below usually returns to the signal handler. We need to
71 * pre-set the correct error code here to ensure that the right values
72 * get saved in sigcontext by ia64_do_signal.
73 */
74 scr->pt.r8 = EINTR;
75 scr->pt.r10 = -1;
76
77 while (1) {
78 current->state = TASK_INTERRUPTIBLE;
79 schedule();
80 if (ia64_do_signal(&oldset, scr, 1))
81 return -EINTR;
82 }
83}
84
85asmlinkage long 44asmlinkage long
86sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, 45sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2,
87 long arg3, long arg4, long arg5, long arg6, long arg7, 46 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 * Note that `init' is a special process: it doesn't get signals it doesn't want to 437 * Note that `init' is a special process: it doesn't get signals it doesn't want to
479 * handle. Thus you cannot kill init even with a SIGKILL even by mistake. 438 * handle. Thus you cannot kill init even with a SIGKILL even by mistake.
480 */ 439 */
481long 440void
482ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) 441ia64_do_signal (struct sigscratch *scr, long in_syscall)
483{ 442{
484 struct k_sigaction ka; 443 struct k_sigaction ka;
444 sigset_t *oldset;
485 siginfo_t info; 445 siginfo_t info;
486 long restart = in_syscall; 446 long restart = in_syscall;
487 long errno = scr->pt.r8; 447 long errno = scr->pt.r8;
@@ -493,9 +453,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
493 * doing anything if so. 453 * doing anything if so.
494 */ 454 */
495 if (!user_mode(&scr->pt)) 455 if (!user_mode(&scr->pt))
496 return 0; 456 return;
497 457
498 if (!oldset) 458 if (test_thread_flag(TIF_RESTORE_SIGMASK))
459 oldset = &current->saved_sigmask;
460 else
499 oldset = &current->blocked; 461 oldset = &current->blocked;
500 462
501 /* 463 /*
@@ -558,8 +520,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
558 * Whee! Actually deliver the signal. If the delivery failed, we need to 520 * Whee! Actually deliver the signal. If the delivery failed, we need to
559 * continue to iterate in this loop so we can deliver the SIGSEGV... 521 * continue to iterate in this loop so we can deliver the SIGSEGV...
560 */ 522 */
561 if (handle_signal(signr, &ka, &info, oldset, scr)) 523 if (handle_signal(signr, &ka, &info, oldset, scr)) {
562 return 1; 524 /* a signal was successfully delivered; the saved
525 * sigmask will have been stored in the signal frame,
526 * and will be restored by sigreturn, so we can simply
527 * clear the TIF_RESTORE_SIGMASK flag */
528 if (test_thread_flag(TIF_RESTORE_SIGMASK))
529 clear_thread_flag(TIF_RESTORE_SIGMASK);
530 return;
531 }
563 } 532 }
564 533
565 /* Did we come from a system call? */ 534 /* Did we come from a system call? */
@@ -585,5 +554,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
585 } 554 }
586 } 555 }
587 } 556 }
588 return 0; 557
558 /* if there's no signal to deliver, we just put the saved sigmask
559 * back */
560 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
561 clear_thread_flag(TIF_RESTORE_SIGMASK);
562 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
563 }
589} 564}