aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/signal.c')
-rw-r--r--arch/parisc/kernel/signal.c45
1 files changed, 15 insertions, 30 deletions
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 594459bde14e..537996955998 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
113 (usp - sigframe_size); 113 (usp - sigframe_size);
114 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); 114 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
115 115
116 regs->orig_r28 = 1; /* no restarts for sigreturn */
117
116#ifdef CONFIG_64BIT 118#ifdef CONFIG_64BIT
117 compat_frame = (struct compat_rt_sigframe __user *)frame; 119 compat_frame = (struct compat_rt_sigframe __user *)frame;
118 120
@@ -437,7 +439,7 @@ give_sigsegv:
437 * OK, we're invoking a handler. 439 * OK, we're invoking a handler.
438 */ 440 */
439 441
440static long 442static void
441handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 443handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
442 struct pt_regs *regs, int in_syscall) 444 struct pt_regs *regs, int in_syscall)
443{ 445{
@@ -447,7 +449,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
447 449
448 /* Set up the stack frame */ 450 /* Set up the stack frame */
449 if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) 451 if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
450 return 0; 452 return;
451 453
452 signal_delivered(sig, info, ka, regs, 454 signal_delivered(sig, info, ka, regs,
453 test_thread_flag(TIF_SINGLESTEP) || 455 test_thread_flag(TIF_SINGLESTEP) ||
@@ -455,13 +457,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
455 457
456 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", 458 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
457 regs->gr[28]); 459 regs->gr[28]);
458
459 return 1;
460} 460}
461 461
462static inline void 462static inline void
463syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) 463syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
464{ 464{
465 if (regs->orig_r28)
466 return;
467 regs->orig_r28 = 1; /* no more restarts */
465 /* Check the return code */ 468 /* Check the return code */
466 switch (regs->gr[28]) { 469 switch (regs->gr[28]) {
467 case -ERESTART_RESTARTBLOCK: 470 case -ERESTART_RESTARTBLOCK:
@@ -482,8 +485,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
482 * we have to do is fiddle the return pointer. 485 * we have to do is fiddle the return pointer.
483 */ 486 */
484 regs->gr[31] -= 8; /* delayed branching */ 487 regs->gr[31] -= 8; /* delayed branching */
485 /* Preserve original r28. */
486 regs->gr[28] = regs->orig_r28;
487 break; 488 break;
488 } 489 }
489} 490}
@@ -491,6 +492,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
491static inline void 492static inline void
492insert_restart_trampoline(struct pt_regs *regs) 493insert_restart_trampoline(struct pt_regs *regs)
493{ 494{
495 if (regs->orig_r28)
496 return;
497 regs->orig_r28 = 1; /* no more restarts */
494 switch(regs->gr[28]) { 498 switch(regs->gr[28]) {
495 case -ERESTART_RESTARTBLOCK: { 499 case -ERESTART_RESTARTBLOCK: {
496 /* Restart the system call - no handlers present */ 500 /* Restart the system call - no handlers present */
@@ -525,9 +529,6 @@ insert_restart_trampoline(struct pt_regs *regs)
525 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); 529 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
526 530
527 regs->gr[31] = regs->gr[30] + 8; 531 regs->gr[31] = regs->gr[30] + 8;
528 /* Preserve original r28. */
529 regs->gr[28] = regs->orig_r28;
530
531 return; 532 return;
532 } 533 }
533 case -ERESTARTNOHAND: 534 case -ERESTARTNOHAND:
@@ -539,9 +540,6 @@ insert_restart_trampoline(struct pt_regs *regs)
539 * slot of the branch external instruction. 540 * slot of the branch external instruction.
540 */ 541 */
541 regs->gr[31] -= 8; 542 regs->gr[31] -= 8;
542 /* Preserve original r28. */
543 regs->gr[28] = regs->orig_r28;
544
545 return; 543 return;
546 } 544 }
547 default: 545 default:
@@ -570,30 +568,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
570 DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n", 568 DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
571 regs, regs->sr[7], in_syscall); 569 regs, regs->sr[7], in_syscall);
572 570
573 /* Everyone else checks to see if they are in kernel mode at 571 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
574 this point and exits if that's the case. I'm not sure why 572 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
575 we would be called in that case, but for some reason we
576 are. */
577
578 /* May need to force signal if handle_signal failed to deliver */
579 while (1) {
580 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
581 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
582 573
583 if (signr <= 0) 574 if (signr > 0) {
584 break;
585
586 /* Restart a system call if necessary. */ 575 /* Restart a system call if necessary. */
587 if (in_syscall) 576 if (in_syscall)
588 syscall_restart(regs, &ka); 577 syscall_restart(regs, &ka);
589 578
590 /* Whee! Actually deliver the signal. If the 579 handle_signal(signr, &info, &ka, regs, in_syscall);
591 delivery failed, we need to continue to iterate in 580 return;
592 this loop so we can deliver the SIGSEGV... */
593 if (handle_signal(signr, &info, &ka, regs, in_syscall))
594 return;
595 } 581 }
596 /* end of while(1) looping forever if we can't force a signal */
597 582
598 /* Did we come from a system call? */ 583 /* Did we come from a system call? */
599 if (in_syscall) 584 if (in_syscall)