diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-01-18 20:44:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-18 22:20:30 -0500 |
commit | f27201da5c8f118cfe266f51447bdd108d5f081d (patch) | |
tree | 9d889f4afec179b5b6f422b58dd36fa7606f3eee /arch | |
parent | 283828f3c19ceb3a64a8544d42cc189003e8b0fe (diff) |
[PATCH] TIF_RESTORE_SIGMASK support for arch/powerpc
Implement the TIF_RESTORE_SIGMASK flag in the new arch/powerpc kernel, for
both 32-bit and 64-bit system call paths.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 20 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 20 | ||||
-rw-r--r-- | arch/powerpc/kernel/systbl.S | 2 |
5 files changed, 40 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index d8da2a35c0a4..f20a67261ec7 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -227,7 +227,7 @@ ret_from_syscall: | |||
227 | MTMSRD(r10) | 227 | MTMSRD(r10) |
228 | lwz r9,TI_FLAGS(r12) | 228 | lwz r9,TI_FLAGS(r12) |
229 | li r8,-_LAST_ERRNO | 229 | li r8,-_LAST_ERRNO |
230 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) | 230 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) |
231 | bne- syscall_exit_work | 231 | bne- syscall_exit_work |
232 | cmplw 0,r3,r8 | 232 | cmplw 0,r3,r8 |
233 | blt+ syscall_exit_cont | 233 | blt+ syscall_exit_cont |
@@ -357,7 +357,7 @@ save_user_nvgprs_cont: | |||
357 | lwz r5,_MSR(r1) | 357 | lwz r5,_MSR(r1) |
358 | andi. r5,r5,MSR_PR | 358 | andi. r5,r5,MSR_PR |
359 | beq ret_from_except | 359 | beq ret_from_except |
360 | andi. r0,r9,_TIF_SIGPENDING | 360 | andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK |
361 | beq ret_from_except | 361 | beq ret_from_except |
362 | b do_user_signal | 362 | b do_user_signal |
363 | 8: | 363 | 8: |
@@ -683,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ | |||
683 | /* Check current_thread_info()->flags */ | 683 | /* Check current_thread_info()->flags */ |
684 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) | 684 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) |
685 | lwz r9,TI_FLAGS(r9) | 685 | lwz r9,TI_FLAGS(r9) |
686 | andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) | 686 | andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) |
687 | bne do_work | 687 | bne do_work |
688 | 688 | ||
689 | restore_user: | 689 | restore_user: |
@@ -917,7 +917,7 @@ recheck: | |||
917 | lwz r9,TI_FLAGS(r9) | 917 | lwz r9,TI_FLAGS(r9) |
918 | andi. r0,r9,_TIF_NEED_RESCHED | 918 | andi. r0,r9,_TIF_NEED_RESCHED |
919 | bne- do_resched | 919 | bne- do_resched |
920 | andi. r0,r9,_TIF_SIGPENDING | 920 | andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK |
921 | beq restore_user | 921 | beq restore_user |
922 | do_user_signal: /* r10 contains MSR_KERNEL here */ | 922 | do_user_signal: /* r10 contains MSR_KERNEL here */ |
923 | ori r10,r10,MSR_EE | 923 | ori r10,r10,MSR_EE |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 542036318866..388f861b8ed1 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -160,7 +160,7 @@ syscall_exit: | |||
160 | mtmsrd r10,1 | 160 | mtmsrd r10,1 |
161 | ld r9,TI_FLAGS(r12) | 161 | ld r9,TI_FLAGS(r12) |
162 | li r11,-_LAST_ERRNO | 162 | li r11,-_LAST_ERRNO |
163 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR) | 163 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK) |
164 | bne- syscall_exit_work | 164 | bne- syscall_exit_work |
165 | cmpld r3,r11 | 165 | cmpld r3,r11 |
166 | ld r5,_CCR(r1) | 166 | ld r5,_CCR(r1) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 7f0d5ce2567d..3747ab0dac3f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -1128,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
1128 | { | 1128 | { |
1129 | siginfo_t info; | 1129 | siginfo_t info; |
1130 | struct k_sigaction ka; | 1130 | struct k_sigaction ka; |
1131 | unsigned int frame, newsp; | 1131 | unsigned int newsp; |
1132 | int signr, ret; | 1132 | int signr, ret; |
1133 | 1133 | ||
1134 | #ifdef CONFIG_PPC32 | 1134 | #ifdef CONFIG_PPC32 |
@@ -1139,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
1139 | } | 1139 | } |
1140 | #endif | 1140 | #endif |
1141 | 1141 | ||
1142 | if (!oldset) | 1142 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
1143 | oldset = ¤t->saved_sigmask; | ||
1144 | else if (!oldset) | ||
1143 | oldset = ¤t->blocked; | 1145 | oldset = ¤t->blocked; |
1144 | 1146 | ||
1145 | newsp = frame = 0; | ||
1146 | |||
1147 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 1147 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
1148 | #ifdef CONFIG_PPC32 | 1148 | #ifdef CONFIG_PPC32 |
1149 | no_signal: | 1149 | no_signal: |
@@ -1173,8 +1173,14 @@ no_signal: | |||
1173 | } | 1173 | } |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | if (signr == 0) | 1176 | if (signr == 0) { |
1177 | /* No signal to deliver -- put the saved sigmask back */ | ||
1178 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
1179 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1180 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
1181 | } | ||
1177 | return 0; /* no signals delivered */ | 1182 | return 0; /* no signals delivered */ |
1183 | } | ||
1178 | 1184 | ||
1179 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size | 1185 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size |
1180 | && !on_sig_stack(regs->gpr[1])) | 1186 | && !on_sig_stack(regs->gpr[1])) |
@@ -1207,6 +1213,10 @@ no_signal: | |||
1207 | sigaddset(¤t->blocked, signr); | 1213 | sigaddset(¤t->blocked, signr); |
1208 | recalc_sigpending(); | 1214 | recalc_sigpending(); |
1209 | spin_unlock_irq(¤t->sighand->siglock); | 1215 | spin_unlock_irq(¤t->sighand->siglock); |
1216 | /* A signal was successfully delivered; the saved sigmask is in | ||
1217 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
1218 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
1219 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1210 | } | 1220 | } |
1211 | 1221 | ||
1212 | return ret; | 1222 | return ret; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index a4a6812e815e..b3193116e686 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -520,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
520 | if (test_thread_flag(TIF_32BIT)) | 520 | if (test_thread_flag(TIF_32BIT)) |
521 | return do_signal32(oldset, regs); | 521 | return do_signal32(oldset, regs); |
522 | 522 | ||
523 | if (!oldset) | 523 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
524 | oldset = ¤t->saved_sigmask; | ||
525 | else if (!oldset) | ||
524 | oldset = ¤t->blocked; | 526 | oldset = ¤t->blocked; |
525 | 527 | ||
526 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 528 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
527 | if (signr > 0) { | 529 | if (signr > 0) { |
530 | int ret; | ||
531 | |||
528 | /* Whee! Actually deliver the signal. */ | 532 | /* Whee! Actually deliver the signal. */ |
529 | if (TRAP(regs) == 0x0C00) | 533 | if (TRAP(regs) == 0x0C00) |
530 | syscall_restart(regs, &ka); | 534 | syscall_restart(regs, &ka); |
@@ -537,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
537 | if (current->thread.dabr) | 541 | if (current->thread.dabr) |
538 | set_dabr(current->thread.dabr); | 542 | set_dabr(current->thread.dabr); |
539 | 543 | ||
540 | return handle_signal(signr, &ka, &info, oldset, regs); | 544 | ret = handle_signal(signr, &ka, &info, oldset, regs); |
545 | |||
546 | /* If a signal was successfully delivered, the saved sigmask is in | ||
547 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
548 | if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
549 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
550 | |||
551 | return ret; | ||
541 | } | 552 | } |
542 | 553 | ||
543 | if (TRAP(regs) == 0x0C00) { /* System Call! */ | 554 | if (TRAP(regs) == 0x0C00) { /* System Call! */ |
@@ -553,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
553 | regs->result = 0; | 564 | regs->result = 0; |
554 | } | 565 | } |
555 | } | 566 | } |
567 | /* No signal to deliver -- put the saved sigmask back */ | ||
568 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
569 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
570 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
571 | } | ||
556 | 572 | ||
557 | return 0; | 573 | return 0; |
558 | } | 574 | } |
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 68013179a503..007b15ee36d2 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S | |||
@@ -321,3 +321,5 @@ SYSCALL(inotify_add_watch) | |||
321 | SYSCALL(inotify_rm_watch) | 321 | SYSCALL(inotify_rm_watch) |
322 | SYSCALL(spu_run) | 322 | SYSCALL(spu_run) |
323 | SYSCALL(spu_create) | 323 | SYSCALL(spu_create) |
324 | COMPAT_SYS(pselect6) | ||
325 | COMPAT_SYS(ppoll) | ||