diff options
Diffstat (limited to 'arch/sparc')
| -rw-r--r-- | arch/sparc/kernel/perf_event.c | 15 | ||||
| -rw-r--r-- | arch/sparc/kernel/signal32.c | 161 | ||||
| -rw-r--r-- | arch/sparc/kernel/signal_32.c | 55 | ||||
| -rw-r--r-- | arch/sparc/kernel/signal_64.c | 45 |
4 files changed, 172 insertions, 104 deletions
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index f9a706759364..0d6deb55a2ae 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c | |||
| @@ -1076,13 +1076,24 @@ static int sparc_pmu_event_init(struct perf_event *event) | |||
| 1076 | break; | 1076 | break; |
| 1077 | 1077 | ||
| 1078 | case PERF_TYPE_RAW: | 1078 | case PERF_TYPE_RAW: |
| 1079 | return -EOPNOTSUPP; | 1079 | pmap = NULL; |
| 1080 | break; | ||
| 1080 | 1081 | ||
| 1081 | default: | 1082 | default: |
| 1082 | return -ENOENT; | 1083 | return -ENOENT; |
| 1083 | 1084 | ||
| 1084 | } | 1085 | } |
| 1085 | 1086 | ||
| 1087 | if (pmap) { | ||
| 1088 | hwc->event_base = perf_event_encode(pmap); | ||
| 1089 | } else { | ||
| 1090 | /* | ||
| 1091 | * User gives us "(encoding << 16) | pic_mask" for | ||
| 1092 | * PERF_TYPE_RAW events. | ||
| 1093 | */ | ||
| 1094 | hwc->event_base = attr->config; | ||
| 1095 | } | ||
| 1096 | |||
| 1086 | /* We save the enable bits in the config_base. */ | 1097 | /* We save the enable bits in the config_base. */ |
| 1087 | hwc->config_base = sparc_pmu->irq_bit; | 1098 | hwc->config_base = sparc_pmu->irq_bit; |
| 1088 | if (!attr->exclude_user) | 1099 | if (!attr->exclude_user) |
| @@ -1092,8 +1103,6 @@ static int sparc_pmu_event_init(struct perf_event *event) | |||
| 1092 | if (!attr->exclude_hv) | 1103 | if (!attr->exclude_hv) |
| 1093 | hwc->config_base |= sparc_pmu->hv_bit; | 1104 | hwc->config_base |= sparc_pmu->hv_bit; |
| 1094 | 1105 | ||
| 1095 | hwc->event_base = perf_event_encode(pmap); | ||
| 1096 | |||
| 1097 | n = 0; | 1106 | n = 0; |
| 1098 | if (event->group_leader != event) { | 1107 | if (event->group_leader != event) { |
| 1099 | n = collect_events(event->group_leader, | 1108 | n = collect_events(event->group_leader, |
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index ea22cd373c64..75fad425e249 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c | |||
| @@ -453,8 +453,66 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | |||
| 453 | return err; | 453 | return err; |
| 454 | } | 454 | } |
| 455 | 455 | ||
| 456 | static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, | 456 | /* The I-cache flush instruction only works in the primary ASI, which |
| 457 | int signo, sigset_t *oldset) | 457 | * right now is the nucleus, aka. kernel space. |
| 458 | * | ||
| 459 | * Therefore we have to kick the instructions out using the kernel | ||
| 460 | * side linear mapping of the physical address backing the user | ||
| 461 | * instructions. | ||
| 462 | */ | ||
| 463 | static void flush_signal_insns(unsigned long address) | ||
| 464 | { | ||
| 465 | unsigned long pstate, paddr; | ||
| 466 | pte_t *ptep, pte; | ||
| 467 | pgd_t *pgdp; | ||
| 468 | pud_t *pudp; | ||
| 469 | pmd_t *pmdp; | ||
| 470 | |||
| 471 | /* Commit all stores of the instructions we are about to flush. */ | ||
| 472 | wmb(); | ||
| 473 | |||
| 474 | /* Disable cross-call reception. In this way even a very wide | ||
| 475 | * munmap() on another cpu can't tear down the page table | ||
| 476 | * hierarchy from underneath us, since that can't complete | ||
| 477 | * until the IPI tlb flush returns. | ||
| 478 | */ | ||
| 479 | |||
| 480 | __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); | ||
| 481 | __asm__ __volatile__("wrpr %0, %1, %%pstate" | ||
| 482 | : : "r" (pstate), "i" (PSTATE_IE)); | ||
| 483 | |||
| 484 | pgdp = pgd_offset(current->mm, address); | ||
| 485 | if (pgd_none(*pgdp)) | ||
| 486 | goto out_irqs_on; | ||
| 487 | pudp = pud_offset(pgdp, address); | ||
| 488 | if (pud_none(*pudp)) | ||
| 489 | goto out_irqs_on; | ||
| 490 | pmdp = pmd_offset(pudp, address); | ||
| 491 | if (pmd_none(*pmdp)) | ||
| 492 | goto out_irqs_on; | ||
| 493 | |||
| 494 | ptep = pte_offset_map(pmdp, address); | ||
| 495 | pte = *ptep; | ||
| 496 | if (!pte_present(pte)) | ||
| 497 | goto out_unmap; | ||
| 498 | |||
| 499 | paddr = (unsigned long) page_address(pte_page(pte)); | ||
| 500 | |||
| 501 | __asm__ __volatile__("flush %0 + %1" | ||
| 502 | : /* no outputs */ | ||
| 503 | : "r" (paddr), | ||
| 504 | "r" (address & (PAGE_SIZE - 1)) | ||
| 505 | : "memory"); | ||
| 506 | |||
| 507 | out_unmap: | ||
| 508 | pte_unmap(ptep); | ||
| 509 | out_irqs_on: | ||
| 510 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); | ||
| 511 | |||
| 512 | } | ||
| 513 | |||
| 514 | static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, | ||
| 515 | int signo, sigset_t *oldset) | ||
| 458 | { | 516 | { |
| 459 | struct signal_frame32 __user *sf; | 517 | struct signal_frame32 __user *sf; |
| 460 | int sigframe_size; | 518 | int sigframe_size; |
| @@ -547,13 +605,7 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 547 | if (ka->ka_restorer) { | 605 | if (ka->ka_restorer) { |
| 548 | regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; | 606 | regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; |
| 549 | } else { | 607 | } else { |
| 550 | /* Flush instruction space. */ | ||
| 551 | unsigned long address = ((unsigned long)&(sf->insns[0])); | 608 | unsigned long address = ((unsigned long)&(sf->insns[0])); |
| 552 | pgd_t *pgdp = pgd_offset(current->mm, address); | ||
| 553 | pud_t *pudp = pud_offset(pgdp, address); | ||
| 554 | pmd_t *pmdp = pmd_offset(pudp, address); | ||
| 555 | pte_t *ptep; | ||
| 556 | pte_t pte; | ||
| 557 | 609 | ||
| 558 | regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); | 610 | regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); |
| 559 | 611 | ||
| @@ -562,34 +614,22 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 562 | if (err) | 614 | if (err) |
| 563 | goto sigsegv; | 615 | goto sigsegv; |
| 564 | 616 | ||
| 565 | preempt_disable(); | 617 | flush_signal_insns(address); |
| 566 | ptep = pte_offset_map(pmdp, address); | ||
| 567 | pte = *ptep; | ||
| 568 | if (pte_present(pte)) { | ||
| 569 | unsigned long page = (unsigned long) | ||
| 570 | page_address(pte_page(pte)); | ||
| 571 | |||
| 572 | wmb(); | ||
| 573 | __asm__ __volatile__("flush %0 + %1" | ||
| 574 | : /* no outputs */ | ||
| 575 | : "r" (page), | ||
| 576 | "r" (address & (PAGE_SIZE - 1)) | ||
| 577 | : "memory"); | ||
| 578 | } | ||
| 579 | pte_unmap(ptep); | ||
| 580 | preempt_enable(); | ||
| 581 | } | 618 | } |
| 582 | return; | 619 | return 0; |
| 583 | 620 | ||
| 584 | sigill: | 621 | sigill: |
| 585 | do_exit(SIGILL); | 622 | do_exit(SIGILL); |
| 623 | return -EINVAL; | ||
| 624 | |||
| 586 | sigsegv: | 625 | sigsegv: |
| 587 | force_sigsegv(signo, current); | 626 | force_sigsegv(signo, current); |
| 627 | return -EFAULT; | ||
| 588 | } | 628 | } |
| 589 | 629 | ||
| 590 | static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, | 630 | static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, |
| 591 | unsigned long signr, sigset_t *oldset, | 631 | unsigned long signr, sigset_t *oldset, |
| 592 | siginfo_t *info) | 632 | siginfo_t *info) |
| 593 | { | 633 | { |
| 594 | struct rt_signal_frame32 __user *sf; | 634 | struct rt_signal_frame32 __user *sf; |
| 595 | int sigframe_size; | 635 | int sigframe_size; |
| @@ -687,12 +727,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 687 | if (ka->ka_restorer) | 727 | if (ka->ka_restorer) |
| 688 | regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; | 728 | regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; |
| 689 | else { | 729 | else { |
| 690 | /* Flush instruction space. */ | ||
| 691 | unsigned long address = ((unsigned long)&(sf->insns[0])); | 730 | unsigned long address = ((unsigned long)&(sf->insns[0])); |
| 692 | pgd_t *pgdp = pgd_offset(current->mm, address); | ||
| 693 | pud_t *pudp = pud_offset(pgdp, address); | ||
| 694 | pmd_t *pmdp = pmd_offset(pudp, address); | ||
| 695 | pte_t *ptep; | ||
| 696 | 731 | ||
| 697 | regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); | 732 | regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); |
| 698 | 733 | ||
| @@ -704,38 +739,32 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 704 | if (err) | 739 | if (err) |
| 705 | goto sigsegv; | 740 | goto sigsegv; |
| 706 | 741 | ||
| 707 | preempt_disable(); | 742 | flush_signal_insns(address); |
| 708 | ptep = pte_offset_map(pmdp, address); | ||
| 709 | if (pte_present(*ptep)) { | ||
| 710 | unsigned long page = (unsigned long) | ||
| 711 | page_address(pte_page(*ptep)); | ||
| 712 | |||
| 713 | wmb(); | ||
| 714 | __asm__ __volatile__("flush %0 + %1" | ||
| 715 | : /* no outputs */ | ||
| 716 | : "r" (page), | ||
| 717 | "r" (address & (PAGE_SIZE - 1)) | ||
| 718 | : "memory"); | ||
| 719 | } | ||
| 720 | pte_unmap(ptep); | ||
| 721 | preempt_enable(); | ||
| 722 | } | 743 | } |
| 723 | return; | 744 | return 0; |
| 724 | 745 | ||
| 725 | sigill: | 746 | sigill: |
| 726 | do_exit(SIGILL); | 747 | do_exit(SIGILL); |
| 748 | return -EINVAL; | ||
| 749 | |||
| 727 | sigsegv: | 750 | sigsegv: |
| 728 | force_sigsegv(signr, current); | 751 | force_sigsegv(signr, current); |
| 752 | return -EFAULT; | ||
| 729 | } | 753 | } |
| 730 | 754 | ||
| 731 | static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, | 755 | static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, |
| 732 | siginfo_t *info, | 756 | siginfo_t *info, |
| 733 | sigset_t *oldset, struct pt_regs *regs) | 757 | sigset_t *oldset, struct pt_regs *regs) |
| 734 | { | 758 | { |
| 759 | int err; | ||
| 760 | |||
| 735 | if (ka->sa.sa_flags & SA_SIGINFO) | 761 | if (ka->sa.sa_flags & SA_SIGINFO) |
| 736 | setup_rt_frame32(ka, regs, signr, oldset, info); | 762 | err = setup_rt_frame32(ka, regs, signr, oldset, info); |
| 737 | else | 763 | else |
| 738 | setup_frame32(ka, regs, signr, oldset); | 764 | err = setup_frame32(ka, regs, signr, oldset); |
| 765 | |||
| 766 | if (err) | ||
| 767 | return err; | ||
| 739 | 768 | ||
| 740 | spin_lock_irq(¤t->sighand->siglock); | 769 | spin_lock_irq(¤t->sighand->siglock); |
| 741 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 770 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
| @@ -743,6 +772,10 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, | |||
| 743 | sigaddset(¤t->blocked,signr); | 772 | sigaddset(¤t->blocked,signr); |
| 744 | recalc_sigpending(); | 773 | recalc_sigpending(); |
| 745 | spin_unlock_irq(¤t->sighand->siglock); | 774 | spin_unlock_irq(¤t->sighand->siglock); |
| 775 | |||
| 776 | tracehook_signal_handler(signr, info, ka, regs, 0); | ||
| 777 | |||
| 778 | return 0; | ||
| 746 | } | 779 | } |
| 747 | 780 | ||
| 748 | static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, | 781 | static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, |
| @@ -789,16 +822,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, | |||
| 789 | if (signr > 0) { | 822 | if (signr > 0) { |
| 790 | if (restart_syscall) | 823 | if (restart_syscall) |
| 791 | syscall_restart32(orig_i0, regs, &ka.sa); | 824 | syscall_restart32(orig_i0, regs, &ka.sa); |
| 792 | handle_signal32(signr, &ka, &info, oldset, regs); | 825 | if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { |
| 793 | 826 | /* A signal was successfully delivered; the saved | |
| 794 | /* A signal was successfully delivered; the saved | 827 | * sigmask will have been stored in the signal frame, |
| 795 | * sigmask will have been stored in the signal frame, | 828 | * and will be restored by sigreturn, so we can simply |
| 796 | * and will be restored by sigreturn, so we can simply | 829 | * clear the TS_RESTORE_SIGMASK flag. |
| 797 | * clear the TS_RESTORE_SIGMASK flag. | 830 | */ |
| 798 | */ | 831 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
| 799 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 832 | } |
| 800 | |||
| 801 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | ||
| 802 | return; | 833 | return; |
| 803 | } | 834 | } |
| 804 | if (restart_syscall && | 835 | if (restart_syscall && |
| @@ -809,12 +840,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, | |||
| 809 | regs->u_regs[UREG_I0] = orig_i0; | 840 | regs->u_regs[UREG_I0] = orig_i0; |
| 810 | regs->tpc -= 4; | 841 | regs->tpc -= 4; |
| 811 | regs->tnpc -= 4; | 842 | regs->tnpc -= 4; |
| 843 | pt_regs_clear_syscall(regs); | ||
| 812 | } | 844 | } |
| 813 | if (restart_syscall && | 845 | if (restart_syscall && |
| 814 | regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { | 846 | regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { |
| 815 | regs->u_regs[UREG_G1] = __NR_restart_syscall; | 847 | regs->u_regs[UREG_G1] = __NR_restart_syscall; |
| 816 | regs->tpc -= 4; | 848 | regs->tpc -= 4; |
| 817 | regs->tnpc -= 4; | 849 | regs->tnpc -= 4; |
| 850 | pt_regs_clear_syscall(regs); | ||
| 818 | } | 851 | } |
| 819 | 852 | ||
| 820 | /* If there's no signal to deliver, we just put the saved sigmask | 853 | /* If there's no signal to deliver, we just put the saved sigmask |
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 9882df92ba0a..5e5c5fd03783 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c | |||
| @@ -315,8 +315,8 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | |||
| 315 | return err; | 315 | return err; |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, | 318 | static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, |
| 319 | int signo, sigset_t *oldset) | 319 | int signo, sigset_t *oldset) |
| 320 | { | 320 | { |
| 321 | struct signal_frame __user *sf; | 321 | struct signal_frame __user *sf; |
| 322 | int sigframe_size, err; | 322 | int sigframe_size, err; |
| @@ -384,16 +384,19 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 384 | /* Flush instruction space. */ | 384 | /* Flush instruction space. */ |
| 385 | flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); | 385 | flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); |
| 386 | } | 386 | } |
| 387 | return; | 387 | return 0; |
| 388 | 388 | ||
| 389 | sigill_and_return: | 389 | sigill_and_return: |
| 390 | do_exit(SIGILL); | 390 | do_exit(SIGILL); |
| 391 | return -EINVAL; | ||
| 392 | |||
| 391 | sigsegv: | 393 | sigsegv: |
| 392 | force_sigsegv(signo, current); | 394 | force_sigsegv(signo, current); |
| 395 | return -EFAULT; | ||
| 393 | } | 396 | } |
| 394 | 397 | ||
| 395 | static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | 398 | static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, |
| 396 | int signo, sigset_t *oldset, siginfo_t *info) | 399 | int signo, sigset_t *oldset, siginfo_t *info) |
| 397 | { | 400 | { |
| 398 | struct rt_signal_frame __user *sf; | 401 | struct rt_signal_frame __user *sf; |
| 399 | int sigframe_size; | 402 | int sigframe_size; |
| @@ -466,22 +469,30 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 466 | /* Flush instruction space. */ | 469 | /* Flush instruction space. */ |
| 467 | flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); | 470 | flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); |
| 468 | } | 471 | } |
| 469 | return; | 472 | return 0; |
| 470 | 473 | ||
| 471 | sigill: | 474 | sigill: |
| 472 | do_exit(SIGILL); | 475 | do_exit(SIGILL); |
| 476 | return -EINVAL; | ||
| 477 | |||
| 473 | sigsegv: | 478 | sigsegv: |
| 474 | force_sigsegv(signo, current); | 479 | force_sigsegv(signo, current); |
| 480 | return -EFAULT; | ||
| 475 | } | 481 | } |
| 476 | 482 | ||
| 477 | static inline void | 483 | static inline int |
| 478 | handle_signal(unsigned long signr, struct k_sigaction *ka, | 484 | handle_signal(unsigned long signr, struct k_sigaction *ka, |
| 479 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | 485 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
| 480 | { | 486 | { |
| 487 | int err; | ||
| 488 | |||
| 481 | if (ka->sa.sa_flags & SA_SIGINFO) | 489 | if (ka->sa.sa_flags & SA_SIGINFO) |
| 482 | setup_rt_frame(ka, regs, signr, oldset, info); | 490 | err = setup_rt_frame(ka, regs, signr, oldset, info); |
| 483 | else | 491 | else |
| 484 | setup_frame(ka, regs, signr, oldset); | 492 | err = setup_frame(ka, regs, signr, oldset); |
| 493 | |||
| 494 | if (err) | ||
| 495 | return err; | ||
| 485 | 496 | ||
| 486 | spin_lock_irq(¤t->sighand->siglock); | 497 | spin_lock_irq(¤t->sighand->siglock); |
| 487 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 498 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
| @@ -489,6 +500,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, | |||
| 489 | sigaddset(¤t->blocked, signr); | 500 | sigaddset(¤t->blocked, signr); |
| 490 | recalc_sigpending(); | 501 | recalc_sigpending(); |
| 491 | spin_unlock_irq(¤t->sighand->siglock); | 502 | spin_unlock_irq(¤t->sighand->siglock); |
| 503 | |||
| 504 | tracehook_signal_handler(signr, info, ka, regs, 0); | ||
| 505 | |||
| 506 | return 0; | ||
| 492 | } | 507 | } |
| 493 | 508 | ||
| 494 | static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, | 509 | static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, |
| @@ -546,17 +561,15 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) | |||
| 546 | if (signr > 0) { | 561 | if (signr > 0) { |
| 547 | if (restart_syscall) | 562 | if (restart_syscall) |
| 548 | syscall_restart(orig_i0, regs, &ka.sa); | 563 | syscall_restart(orig_i0, regs, &ka.sa); |
| 549 | handle_signal(signr, &ka, &info, oldset, regs); | 564 | if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { |
| 550 | 565 | /* a signal was successfully delivered; the saved | |
| 551 | /* a signal was successfully delivered; the saved | 566 | * sigmask will have been stored in the signal frame, |
| 552 | * sigmask will have been stored in the signal frame, | 567 | * and will be restored by sigreturn, so we can simply |
| 553 | * and will be restored by sigreturn, so we can simply | 568 | * clear the TIF_RESTORE_SIGMASK flag. |
| 554 | * clear the TIF_RESTORE_SIGMASK flag. | 569 | */ |
| 555 | */ | 570 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 556 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 571 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
| 557 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 572 | } |
| 558 | |||
| 559 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | ||
| 560 | return; | 573 | return; |
| 561 | } | 574 | } |
| 562 | if (restart_syscall && | 575 | if (restart_syscall && |
| @@ -567,12 +580,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) | |||
| 567 | regs->u_regs[UREG_I0] = orig_i0; | 580 | regs->u_regs[UREG_I0] = orig_i0; |
| 568 | regs->pc -= 4; | 581 | regs->pc -= 4; |
| 569 | regs->npc -= 4; | 582 | regs->npc -= 4; |
| 583 | pt_regs_clear_syscall(regs); | ||
| 570 | } | 584 | } |
| 571 | if (restart_syscall && | 585 | if (restart_syscall && |
| 572 | regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { | 586 | regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { |
| 573 | regs->u_regs[UREG_G1] = __NR_restart_syscall; | 587 | regs->u_regs[UREG_G1] = __NR_restart_syscall; |
| 574 | regs->pc -= 4; | 588 | regs->pc -= 4; |
| 575 | regs->npc -= 4; | 589 | regs->npc -= 4; |
| 590 | pt_regs_clear_syscall(regs); | ||
| 576 | } | 591 | } |
| 577 | 592 | ||
| 578 | /* if there's no signal to deliver, we just put the saved sigmask | 593 | /* if there's no signal to deliver, we just put the saved sigmask |
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 9fa48c30037e..006fe4515886 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c | |||
| @@ -409,7 +409,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * | |||
| 409 | return (void __user *) sp; | 409 | return (void __user *) sp; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | static inline void | 412 | static inline int |
| 413 | setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | 413 | setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, |
| 414 | int signo, sigset_t *oldset, siginfo_t *info) | 414 | int signo, sigset_t *oldset, siginfo_t *info) |
| 415 | { | 415 | { |
| @@ -483,26 +483,37 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 483 | } | 483 | } |
| 484 | /* 4. return to kernel instructions */ | 484 | /* 4. return to kernel instructions */ |
| 485 | regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; | 485 | regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; |
| 486 | return; | 486 | return 0; |
| 487 | 487 | ||
| 488 | sigill: | 488 | sigill: |
| 489 | do_exit(SIGILL); | 489 | do_exit(SIGILL); |
| 490 | return -EINVAL; | ||
| 491 | |||
| 490 | sigsegv: | 492 | sigsegv: |
| 491 | force_sigsegv(signo, current); | 493 | force_sigsegv(signo, current); |
| 494 | return -EFAULT; | ||
| 492 | } | 495 | } |
| 493 | 496 | ||
| 494 | static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, | 497 | static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, |
| 495 | siginfo_t *info, | 498 | siginfo_t *info, |
| 496 | sigset_t *oldset, struct pt_regs *regs) | 499 | sigset_t *oldset, struct pt_regs *regs) |
| 497 | { | 500 | { |
| 498 | setup_rt_frame(ka, regs, signr, oldset, | 501 | int err; |
| 499 | (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); | 502 | |
| 503 | err = setup_rt_frame(ka, regs, signr, oldset, | ||
| 504 | (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); | ||
| 505 | if (err) | ||
| 506 | return err; | ||
| 500 | spin_lock_irq(¤t->sighand->siglock); | 507 | spin_lock_irq(¤t->sighand->siglock); |
| 501 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 508 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
| 502 | if (!(ka->sa.sa_flags & SA_NOMASK)) | 509 | if (!(ka->sa.sa_flags & SA_NOMASK)) |
| 503 | sigaddset(¤t->blocked,signr); | 510 | sigaddset(¤t->blocked,signr); |
| 504 | recalc_sigpending(); | 511 | recalc_sigpending(); |
| 505 | spin_unlock_irq(¤t->sighand->siglock); | 512 | spin_unlock_irq(¤t->sighand->siglock); |
| 513 | |||
| 514 | tracehook_signal_handler(signr, info, ka, regs, 0); | ||
| 515 | |||
| 516 | return 0; | ||
| 506 | } | 517 | } |
| 507 | 518 | ||
| 508 | static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, | 519 | static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, |
| @@ -571,16 +582,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) | |||
| 571 | if (signr > 0) { | 582 | if (signr > 0) { |
| 572 | if (restart_syscall) | 583 | if (restart_syscall) |
| 573 | syscall_restart(orig_i0, regs, &ka.sa); | 584 | syscall_restart(orig_i0, regs, &ka.sa); |
| 574 | handle_signal(signr, &ka, &info, oldset, regs); | 585 | if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { |
| 575 | 586 | /* A signal was successfully delivered; the saved | |
| 576 | /* A signal was successfully delivered; the saved | 587 | * sigmask will have been stored in the signal frame, |
| 577 | * sigmask will have been stored in the signal frame, | 588 | * and will be restored by sigreturn, so we can simply |
| 578 | * and will be restored by sigreturn, so we can simply | 589 | * clear the TS_RESTORE_SIGMASK flag. |
| 579 | * clear the TS_RESTORE_SIGMASK flag. | 590 | */ |
| 580 | */ | 591 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
| 581 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 592 | } |
| 582 | |||
| 583 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | ||
| 584 | return; | 593 | return; |
| 585 | } | 594 | } |
| 586 | if (restart_syscall && | 595 | if (restart_syscall && |
| @@ -591,12 +600,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) | |||
| 591 | regs->u_regs[UREG_I0] = orig_i0; | 600 | regs->u_regs[UREG_I0] = orig_i0; |
| 592 | regs->tpc -= 4; | 601 | regs->tpc -= 4; |
| 593 | regs->tnpc -= 4; | 602 | regs->tnpc -= 4; |
| 603 | pt_regs_clear_syscall(regs); | ||
| 594 | } | 604 | } |
| 595 | if (restart_syscall && | 605 | if (restart_syscall && |
| 596 | regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { | 606 | regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { |
| 597 | regs->u_regs[UREG_G1] = __NR_restart_syscall; | 607 | regs->u_regs[UREG_G1] = __NR_restart_syscall; |
| 598 | regs->tpc -= 4; | 608 | regs->tpc -= 4; |
| 599 | regs->tnpc -= 4; | 609 | regs->tnpc -= 4; |
| 610 | pt_regs_clear_syscall(regs); | ||
| 600 | } | 611 | } |
| 601 | 612 | ||
| 602 | /* If there's no signal to deliver, we just put the saved sigmask | 613 | /* If there's no signal to deliver, we just put the saved sigmask |
