aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle McMartin <kyle@parisc-linux.org>2007-01-08 16:28:06 -0500
committerKyle McMartin <kyle@athena.road.mcmartin.ca>2007-02-17 01:06:04 -0500
commit4650f0a5832033c78690811aa9b171764c11fc0f (patch)
tree8f201cd0f556780b5300d0f0e93e30eb31839190
parent0bbdac0897a48f415eb788bf3263c92bd5e97ffb (diff)
[PARISC] Add TIF_RESTORE_SIGMASK support
And unmask the pselect6/ppoll system calls. Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
-rw-r--r--arch/parisc/kernel/entry.S141
-rw-r--r--arch/parisc/kernel/signal.c72
-rw-r--r--arch/parisc/kernel/syscall_table.S6
-rw-r--r--include/asm-parisc/thread_info.h4
-rw-r--r--include/asm-parisc/unistd.h2
5 files changed, 88 insertions, 137 deletions
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 39a12c1fc6f5..f965673e6863 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -978,11 +978,39 @@ intr_check_resched:
978 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ 978 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
979 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */ 979 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
980 980
981 .import do_notify_resume,code
981intr_check_sig: 982intr_check_sig:
982 /* As above */ 983 /* As above */
983 mfctl %cr30,%r1 984 mfctl %cr30,%r1
984 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */ 985 LDREG TI_FLAGS(%r1),%r19
985 bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */ 986 load32 (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r20
987 and,COND(<>) %r19, %r20, %r0
988 b,n intr_restore /* skip past if we've nothing to do */
989
990 /* This check is critical to having LWS
991 * working. The IASQ is zero on the gateway
992 * page and we cannot deliver any signals until
993 * we get off the gateway page.
994 *
995 * Only do signals if we are returning to user space
996 */
997 LDREG PT_IASQ0(%r16), %r20
998 CMPIB= 0,%r20,intr_restore /* backward */
999 nop
1000 LDREG PT_IASQ1(%r16), %r20
1001 CMPIB= 0,%r20,intr_restore /* backward */
1002 nop
1003
1004 copy %r0, %r25 /* long in_syscall = 0 */
1005#ifdef CONFIG_64BIT
1006 ldo -16(%r30),%r29 /* Reference param save area */
1007#endif
1008
1009 BL do_notify_resume,%r2
1010 copy %r16, %r26 /* struct pt_regs *regs */
1011
1012 b intr_check_sig
1013 nop
986 1014
987intr_restore: 1015intr_restore:
988 copy %r16,%r29 1016 copy %r16,%r29
@@ -1072,35 +1100,6 @@ intr_do_preempt:
1072 b,n intr_restore /* ssm PSW_SM_I done by intr_restore */ 1100 b,n intr_restore /* ssm PSW_SM_I done by intr_restore */
1073#endif /* CONFIG_PREEMPT */ 1101#endif /* CONFIG_PREEMPT */
1074 1102
1075 .import do_signal,code
1076intr_do_signal:
1077 /*
1078 This check is critical to having LWS
1079 working. The IASQ is zero on the gateway
1080 page and we cannot deliver any signals until
1081 we get off the gateway page.
1082
1083 Only do signals if we are returning to user space
1084 */
1085 LDREG PT_IASQ0(%r16), %r20
1086 CMPIB= 0,%r20,intr_restore /* backward */
1087 nop
1088 LDREG PT_IASQ1(%r16), %r20
1089 CMPIB= 0,%r20,intr_restore /* backward */
1090 nop
1091
1092 copy %r0, %r24 /* unsigned long in_syscall */
1093 copy %r16, %r25 /* struct pt_regs *regs */
1094#ifdef CONFIG_64BIT
1095 ldo -16(%r30),%r29 /* Reference param save area */
1096#endif
1097
1098 BL do_signal,%r2
1099 copy %r0, %r26 /* sigset_t *oldset = NULL */
1100
1101 b intr_check_sig
1102 nop
1103
1104 /* 1103 /*
1105 * External interrupts. 1104 * External interrupts.
1106 */ 1105 */
@@ -2024,32 +2023,6 @@ sys32_sigaltstack_wrapper:
2024 nop 2023 nop
2025#endif 2024#endif
2026 2025
2027 .export sys_rt_sigsuspend_wrapper
2028sys_rt_sigsuspend_wrapper:
2029 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2030 ldo TASK_REGS(%r1),%r24
2031 reg_save %r24
2032
2033 STREG %r2, -RP_OFFSET(%r30)
2034#ifdef CONFIG_64BIT
2035 ldo FRAME_SIZE(%r30), %r30
2036 BL sys_rt_sigsuspend,%r2
2037 ldo -16(%r30),%r29 /* Reference param save area */
2038#else
2039 BL sys_rt_sigsuspend,%r2
2040 ldo FRAME_SIZE(%r30), %r30
2041#endif
2042
2043 ldo -FRAME_SIZE(%r30), %r30
2044 LDREG -RP_OFFSET(%r30), %r2
2045
2046 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2047 ldo TASK_REGS(%r1),%r1
2048 reg_restore %r1
2049
2050 bv %r0(%r2)
2051 nop
2052
2053 .export syscall_exit 2026 .export syscall_exit
2054syscall_exit: 2027syscall_exit:
2055 2028
@@ -2115,9 +2088,35 @@ syscall_check_resched:
2115 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */ 2088 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
2116 bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */ 2089 bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
2117 2090
2091 .import do_signal,code
2118syscall_check_sig: 2092syscall_check_sig:
2119 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */ 2093 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
2120 bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */ 2094 load32 (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26
2095 and,COND(<>) %r19, %r26, %r0
2096 b,n syscall_restore /* skip past if we've nothing to do */
2097
2098syscall_do_signal:
2099 /* Save callee-save registers (for sigcontext).
2100 * FIXME: After this point the process structure should be
2101 * consistent with all the relevant state of the process
2102 * before the syscall. We need to verify this.
2103 */
2104 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2105 ldo TASK_REGS(%r1), %r26 /* struct pt_regs *regs */
2106 reg_save %r26
2107
2108#ifdef CONFIG_64BIT
2109 ldo -16(%r30),%r29 /* Reference param save area */
2110#endif
2111
2112 BL do_notify_resume,%r2
2113 ldi 1, %r25 /* long in_syscall = 1 */
2114
2115 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2116 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
2117 reg_restore %r20
2118
2119 b,n syscall_check_sig
2121 2120
2122syscall_restore: 2121syscall_restore:
2123 /* Are we being ptraced? */ 2122 /* Are we being ptraced? */
@@ -2256,30 +2255,6 @@ syscall_do_resched:
2256 b syscall_check_bh /* if resched, we start over again */ 2255 b syscall_check_bh /* if resched, we start over again */
2257 nop 2256 nop
2258 2257
2259 .import do_signal,code
2260syscall_do_signal:
2261 /* Save callee-save registers (for sigcontext).
2262 FIXME: After this point the process structure should be
2263 consistent with all the relevant state of the process
2264 before the syscall. We need to verify this. */
2265 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2266 ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
2267 reg_save %r25
2268
2269 ldi 1, %r24 /* unsigned long in_syscall */
2270
2271#ifdef CONFIG_64BIT
2272 ldo -16(%r30),%r29 /* Reference param save area */
2273#endif
2274 BL do_signal,%r2
2275 copy %r0, %r26 /* sigset_t *oldset = NULL */
2276
2277 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2278 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
2279 reg_restore %r20
2280
2281 b,n syscall_check_sig
2282
2283 /* 2258 /*
2284 * get_register is used by the non access tlb miss handlers to 2259 * get_register is used by the non access tlb miss handlers to
2285 * copy the value of the general register specified in r8 into 2260 * copy the value of the general register specified in r8 into
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index ee6653edeb7a..8d781b0e668b 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -59,8 +59,6 @@
59 * this. */ 59 * this. */
60#define A(__x) ((unsigned long)(__x)) 60#define A(__x) ((unsigned long)(__x))
61 61
62int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
63
64/* 62/*
65 * Atomically swap in the new signal mask, and wait for a signal. 63 * Atomically swap in the new signal mask, and wait for a signal.
66 */ 64 */
@@ -68,49 +66,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
68#include "sys32.h" 66#include "sys32.h"
69#endif 67#endif
70 68
71asmlinkage int
72sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
73{
74 sigset_t saveset, newset;
75#ifdef __LP64__
76 compat_sigset_t newset32;
77
78 if (is_compat_task()) {
79 /* XXX: Don't preclude handling different sized sigset_t's. */
80 if (sigsetsize != sizeof(compat_sigset_t))
81 return -EINVAL;
82 if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
83 return -EFAULT;
84 sigset_32to64(&newset,&newset32);
85
86 } else
87#endif
88 {
89 /* XXX: Don't preclude handling different sized sigset_t's. */
90 if (sigsetsize != sizeof(sigset_t))
91 return -EINVAL;
92
93 if (copy_from_user(&newset, unewset, sizeof(newset)))
94 return -EFAULT;
95 }
96
97 sigdelsetmask(&newset, ~_BLOCKABLE);
98
99 spin_lock_irq(&current->sighand->siglock);
100 saveset = current->blocked;
101 current->blocked = newset;
102 recalc_sigpending();
103 spin_unlock_irq(&current->sighand->siglock);
104
105 regs->gr[28] = -EINTR;
106 while (1) {
107 current->state = TASK_INTERRUPTIBLE;
108 schedule();
109 if (do_signal(&saveset, regs, 1))
110 return -EINTR;
111 }
112}
113
114/* 69/*
115 * Do a signal return - restore sigcontext. 70 * Do a signal return - restore sigcontext.
116 */ 71 */
@@ -528,12 +483,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
528 * us due to the magic of delayed branching. 483 * us due to the magic of delayed branching.
529 */ 484 */
530 485
531asmlinkage int 486asmlinkage void
532do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) 487do_signal(struct pt_regs *regs, long in_syscall)
533{ 488{
534 siginfo_t info; 489 siginfo_t info;
535 struct k_sigaction ka; 490 struct k_sigaction ka;
536 int signr; 491 int signr;
492 sigset_t *oldset;
537 493
538 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", 494 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
539 oldset, regs, regs->sr[7], in_syscall); 495 oldset, regs, regs->sr[7], in_syscall);
@@ -543,7 +499,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
543 we would be called in that case, but for some reason we 499 we would be called in that case, but for some reason we
544 are. */ 500 are. */
545 501
546 if (!oldset) 502 if (test_thread_flag(TIF_RESTORE_SIGMASK))
503 oldset = &current->saved_sigmask;
504 else
547 oldset = &current->blocked; 505 oldset = &current->blocked;
548 506
549 DBG(1,"do_signal: oldset %08lx / %08lx\n", 507 DBG(1,"do_signal: oldset %08lx / %08lx\n",
@@ -592,7 +550,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
592 if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { 550 if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
593 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", 551 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
594 regs->gr[28]); 552 regs->gr[28]);
595 return 1; 553 if (test_thread_flag(TIF_RESTORE_SIGMASK))
554 clear_thread_flag(TIF_RESTORE_SIGMASK);
555 return;
596 } 556 }
597 } 557 }
598 /* end of while(1) looping forever if we can't force a signal */ 558 /* end of while(1) looping forever if we can't force a signal */
@@ -653,5 +613,17 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
653 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 613 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
654 regs->gr[28]); 614 regs->gr[28]);
655 615
656 return 0; 616 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
617 clear_thread_flag(TIF_RESTORE_SIGMASK);
618 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
619 }
620
621 return;
622}
623
624void do_notify_resume(struct pt_regs *regs, long in_syscall)
625{
626 if (test_thread_flag(TIF_SIGPENDING) ||
627 test_thread_flag(TIF_RESTORE_SIGMASK))
628 do_signal(regs, in_syscall);
657} 629}
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 15d9c635d6a6..7f037b72ad03 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -283,7 +283,7 @@
283 * struct from a 32-bit user-space app. 283 * struct from a 32-bit user-space app.
284 */ 284 */
285 ENTRY_SAME(rt_sigqueueinfo) 285 ENTRY_SAME(rt_sigqueueinfo)
286 ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */ 286 ENTRY_COMP(rt_sigsuspend)
287 ENTRY_SAME(chown) /* 180 */ 287 ENTRY_SAME(chown) /* 180 */
288 /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */ 288 /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
289 ENTRY_COMP(setsockopt) 289 ENTRY_COMP(setsockopt)
@@ -377,8 +377,8 @@
377 ENTRY_SAME(inotify_init) 377 ENTRY_SAME(inotify_init)
378 ENTRY_SAME(inotify_add_watch) /* 270 */ 378 ENTRY_SAME(inotify_add_watch) /* 270 */
379 ENTRY_SAME(inotify_rm_watch) 379 ENTRY_SAME(inotify_rm_watch)
380 ENTRY_SAME(ni_syscall) /* 271 ENTRY_COMP(pselect6) */ 380 ENTRY_COMP(pselect6)
381 ENTRY_SAME(ni_syscall) /* 272 ENTRY_COMP(ppoll) */ 381 ENTRY_COMP(ppoll)
382 ENTRY_SAME(migrate_pages) 382 ENTRY_SAME(migrate_pages)
383 ENTRY_COMP(openat) /* 275 */ 383 ENTRY_COMP(openat) /* 275 */
384 ENTRY_SAME(mkdirat) 384 ENTRY_SAME(mkdirat)
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index f2f83b04cd8b..949314cf6188 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -62,6 +62,7 @@ struct thread_info {
62#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling TIF_NEED_RESCHED */ 62#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling TIF_NEED_RESCHED */
63#define TIF_32BIT 5 /* 32 bit binary */ 63#define TIF_32BIT 5 /* 32 bit binary */
64#define TIF_MEMDIE 6 64#define TIF_MEMDIE 6
65#define TIF_RESTORE_SIGMASK 7 /* restore saved signal mask */
65 66
66#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) 67#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
67#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) 68#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
@@ -69,9 +70,10 @@ struct thread_info {
69#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) 70#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
70#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) 71#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
71#define _TIF_32BIT (1 << TIF_32BIT) 72#define _TIF_32BIT (1 << TIF_32BIT)
73#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
72 74
73#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ 75#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
74 _TIF_NEED_RESCHED) 76 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
75 77
76#endif /* __KERNEL__ */ 78#endif /* __KERNEL__ */
77 79
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 3fb37cfcb864..7c1bb8b0a96b 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -955,6 +955,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
955#define __ARCH_WANT_SYS_SIGPENDING 955#define __ARCH_WANT_SYS_SIGPENDING
956#define __ARCH_WANT_SYS_SIGPROCMASK 956#define __ARCH_WANT_SYS_SIGPROCMASK
957#define __ARCH_WANT_SYS_RT_SIGACTION 957#define __ARCH_WANT_SYS_RT_SIGACTION
958#define __ARCH_WANT_SYS_RT_SIGSUSPEND
959#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
958 960
959#endif /* __ASSEMBLY__ */ 961#endif /* __ASSEMBLY__ */
960 962