diff options
Diffstat (limited to 'arch/powerpc/kernel')
-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 | 76 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 56 | ||||
-rw-r--r-- | arch/powerpc/kernel/systbl.S | 2 |
5 files changed, 45 insertions, 99 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 177bba78fb0b..3747ab0dac3f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs); | |||
252 | /* | 252 | /* |
253 | * Atomically swap in the new signal mask, and wait for a signal. | 253 | * Atomically swap in the new signal mask, and wait for a signal. |
254 | */ | 254 | */ |
255 | long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, | 255 | long sys_sigsuspend(old_sigset_t mask) |
256 | struct pt_regs *regs) | ||
257 | { | 256 | { |
258 | sigset_t saveset; | 257 | sigset_t saveset; |
259 | 258 | ||
@@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, | |||
264 | recalc_sigpending(); | 263 | recalc_sigpending(); |
265 | spin_unlock_irq(¤t->sighand->siglock); | 264 | spin_unlock_irq(¤t->sighand->siglock); |
266 | 265 | ||
267 | regs->result = -EINTR; | 266 | current->state = TASK_INTERRUPTIBLE; |
268 | regs->gpr[3] = EINTR; | 267 | schedule(); |
269 | regs->ccr |= 0x10000000; | 268 | set_thread_flag(TIF_RESTORE_SIGMASK); |
270 | while (1) { | 269 | return -ERESTARTNOHAND; |
271 | current->state = TASK_INTERRUPTIBLE; | ||
272 | schedule(); | ||
273 | if (do_signal(&saveset, regs)) { | ||
274 | set_thread_flag(TIF_RESTOREALL); | ||
275 | return 0; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | long sys_rt_sigsuspend( | ||
281 | #ifdef CONFIG_PPC64 | ||
282 | compat_sigset_t __user *unewset, | ||
283 | #else | ||
284 | sigset_t __user *unewset, | ||
285 | #endif | ||
286 | size_t sigsetsize, int p3, int p4, | ||
287 | int p6, int p7, struct pt_regs *regs) | ||
288 | { | ||
289 | sigset_t saveset, newset; | ||
290 | |||
291 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
292 | if (sigsetsize != sizeof(sigset_t)) | ||
293 | return -EINVAL; | ||
294 | |||
295 | if (get_sigset_t(&newset, unewset)) | ||
296 | return -EFAULT; | ||
297 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
298 | |||
299 | spin_lock_irq(¤t->sighand->siglock); | ||
300 | saveset = current->blocked; | ||
301 | current->blocked = newset; | ||
302 | recalc_sigpending(); | ||
303 | spin_unlock_irq(¤t->sighand->siglock); | ||
304 | |||
305 | regs->result = -EINTR; | ||
306 | regs->gpr[3] = EINTR; | ||
307 | regs->ccr |= 0x10000000; | ||
308 | while (1) { | ||
309 | current->state = TASK_INTERRUPTIBLE; | ||
310 | schedule(); | ||
311 | if (do_signal(&saveset, regs)) { | ||
312 | set_thread_flag(TIF_RESTOREALL); | ||
313 | return 0; | ||
314 | } | ||
315 | } | ||
316 | } | 270 | } |
317 | 271 | ||
318 | #ifdef CONFIG_PPC32 | 272 | #ifdef CONFIG_PPC32 |
@@ -1174,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
1174 | { | 1128 | { |
1175 | siginfo_t info; | 1129 | siginfo_t info; |
1176 | struct k_sigaction ka; | 1130 | struct k_sigaction ka; |
1177 | unsigned int frame, newsp; | 1131 | unsigned int newsp; |
1178 | int signr, ret; | 1132 | int signr, ret; |
1179 | 1133 | ||
1180 | #ifdef CONFIG_PPC32 | 1134 | #ifdef CONFIG_PPC32 |
@@ -1185,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
1185 | } | 1139 | } |
1186 | #endif | 1140 | #endif |
1187 | 1141 | ||
1188 | if (!oldset) | 1142 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
1143 | oldset = ¤t->saved_sigmask; | ||
1144 | else if (!oldset) | ||
1189 | oldset = ¤t->blocked; | 1145 | oldset = ¤t->blocked; |
1190 | 1146 | ||
1191 | newsp = frame = 0; | ||
1192 | |||
1193 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 1147 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
1194 | #ifdef CONFIG_PPC32 | 1148 | #ifdef CONFIG_PPC32 |
1195 | no_signal: | 1149 | no_signal: |
@@ -1219,8 +1173,14 @@ no_signal: | |||
1219 | } | 1173 | } |
1220 | } | 1174 | } |
1221 | 1175 | ||
1222 | 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 | } | ||
1223 | return 0; /* no signals delivered */ | 1182 | return 0; /* no signals delivered */ |
1183 | } | ||
1224 | 1184 | ||
1225 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size | 1185 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size |
1226 | && !on_sig_stack(regs->gpr[1])) | 1186 | && !on_sig_stack(regs->gpr[1])) |
@@ -1253,6 +1213,10 @@ no_signal: | |||
1253 | sigaddset(¤t->blocked, signr); | 1213 | sigaddset(¤t->blocked, signr); |
1254 | recalc_sigpending(); | 1214 | recalc_sigpending(); |
1255 | 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); | ||
1256 | } | 1220 | } |
1257 | 1221 | ||
1258 | return ret; | 1222 | return ret; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 7b9d999e2115..b3193116e686 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -67,42 +67,6 @@ struct rt_sigframe { | |||
67 | char abigap[288]; | 67 | char abigap[288]; |
68 | } __attribute__ ((aligned (16))); | 68 | } __attribute__ ((aligned (16))); |
69 | 69 | ||
70 | |||
71 | /* | ||
72 | * Atomically swap in the new signal mask, and wait for a signal. | ||
73 | */ | ||
74 | long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4, | ||
75 | int p6, int p7, struct pt_regs *regs) | ||
76 | { | ||
77 | sigset_t saveset, newset; | ||
78 | |||
79 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
80 | if (sigsetsize != sizeof(sigset_t)) | ||
81 | return -EINVAL; | ||
82 | |||
83 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
84 | return -EFAULT; | ||
85 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
86 | |||
87 | spin_lock_irq(¤t->sighand->siglock); | ||
88 | saveset = current->blocked; | ||
89 | current->blocked = newset; | ||
90 | recalc_sigpending(); | ||
91 | spin_unlock_irq(¤t->sighand->siglock); | ||
92 | |||
93 | regs->result = -EINTR; | ||
94 | regs->gpr[3] = EINTR; | ||
95 | regs->ccr |= 0x10000000; | ||
96 | while (1) { | ||
97 | current->state = TASK_INTERRUPTIBLE; | ||
98 | schedule(); | ||
99 | if (do_signal(&saveset, regs)) { | ||
100 | set_thread_flag(TIF_RESTOREALL); | ||
101 | return 0; | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | |||
106 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, | 70 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, |
107 | unsigned long r6, unsigned long r7, unsigned long r8, | 71 | unsigned long r6, unsigned long r7, unsigned long r8, |
108 | struct pt_regs *regs) | 72 | struct pt_regs *regs) |
@@ -556,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
556 | if (test_thread_flag(TIF_32BIT)) | 520 | if (test_thread_flag(TIF_32BIT)) |
557 | return do_signal32(oldset, regs); | 521 | return do_signal32(oldset, regs); |
558 | 522 | ||
559 | if (!oldset) | 523 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
524 | oldset = ¤t->saved_sigmask; | ||
525 | else if (!oldset) | ||
560 | oldset = ¤t->blocked; | 526 | oldset = ¤t->blocked; |
561 | 527 | ||
562 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 528 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
563 | if (signr > 0) { | 529 | if (signr > 0) { |
530 | int ret; | ||
531 | |||
564 | /* Whee! Actually deliver the signal. */ | 532 | /* Whee! Actually deliver the signal. */ |
565 | if (TRAP(regs) == 0x0C00) | 533 | if (TRAP(regs) == 0x0C00) |
566 | syscall_restart(regs, &ka); | 534 | syscall_restart(regs, &ka); |
@@ -573,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
573 | if (current->thread.dabr) | 541 | if (current->thread.dabr) |
574 | set_dabr(current->thread.dabr); | 542 | set_dabr(current->thread.dabr); |
575 | 543 | ||
576 | 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; | ||
577 | } | 552 | } |
578 | 553 | ||
579 | if (TRAP(regs) == 0x0C00) { /* System Call! */ | 554 | if (TRAP(regs) == 0x0C00) { /* System Call! */ |
@@ -589,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
589 | regs->result = 0; | 564 | regs->result = 0; |
590 | } | 565 | } |
591 | } | 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 | } | ||
592 | 572 | ||
593 | return 0; | 573 | return 0; |
594 | } | 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) | ||