27
27
*/
28
28
#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
29
29
#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
30
- #define SWI_SYS_RESTART (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)
31
30
32
31
/*
33
32
* With EABI, the syscall number has to be loaded into r7.
@@ -47,18 +46,6 @@ const unsigned long sigreturn_codes[7] = {
47
46
MOV_R7_NR_RT_SIGRETURN , SWI_SYS_RT_SIGRETURN , SWI_THUMB_RT_SIGRETURN ,
48
47
};
49
48
50
- /*
51
- * Either we support OABI only, or we have EABI with the OABI
52
- * compat layer enabled. In the later case we don't know if
53
- * user space is EABI or not, and if not we must not clobber r7.
54
- * Always using the OABI syscall solves that issue and works for
55
- * all those cases.
56
- */
57
- const unsigned long syscall_restart_code [2 ] = {
58
- SWI_SYS_RESTART , /* swi __NR_restart_syscall */
59
- 0xe49df004 , /* ldr pc, [sp], #4 */
60
- };
61
-
62
49
/*
63
50
* atomically swap in the new signal mask, and wait for a signal.
64
51
*/
@@ -582,12 +569,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
582
569
* the kernel can handle, and then we build all the user-level signal handling
583
570
* stack-frames in one go after that.
584
571
*/
585
- static void do_signal (struct pt_regs * regs , int syscall )
572
+ static int do_signal (struct pt_regs * regs , int syscall )
586
573
{
587
574
unsigned int retval = 0 , continue_addr = 0 , restart_addr = 0 ;
588
575
struct k_sigaction ka ;
589
576
siginfo_t info ;
590
577
int signr ;
578
+ int restart = 0 ;
591
579
592
580
/*
593
581
* If we were from a system call, check for system call restarting...
@@ -602,15 +590,15 @@ static void do_signal(struct pt_regs *regs, int syscall)
602
590
* debugger will see the already changed PSW.
603
591
*/
604
592
switch (retval ) {
593
+ case - ERESTART_RESTARTBLOCK :
594
+ restart -= 2 ;
605
595
case - ERESTARTNOHAND :
606
596
case - ERESTARTSYS :
607
597
case - ERESTARTNOINTR :
598
+ restart ++ ;
608
599
regs -> ARM_r0 = regs -> ARM_ORIG_r0 ;
609
600
regs -> ARM_pc = restart_addr ;
610
601
break ;
611
- case - ERESTART_RESTARTBLOCK :
612
- regs -> ARM_r0 = - EINTR ;
613
- break ;
614
602
}
615
603
}
616
604
@@ -619,14 +607,17 @@ static void do_signal(struct pt_regs *regs, int syscall)
619
607
* point the debugger may change all our registers ...
620
608
*/
621
609
signr = get_signal_to_deliver (& info , & ka , regs , NULL );
610
+ /*
611
+ * Depending on the signal settings we may need to revert the
612
+ * decision to restart the system call. But skip this if a
613
+ * debugger has chosen to restart at a different PC.
614
+ */
615
+ if (regs -> ARM_pc != restart_addr )
616
+ restart = 0 ;
622
617
if (signr > 0 ) {
623
- /*
624
- * Depending on the signal settings we may need to revert the
625
- * decision to restart the system call. But skip this if a
626
- * debugger has chosen to restart at a different PC.
627
- */
628
- if (regs -> ARM_pc == restart_addr ) {
629
- if (retval == - ERESTARTNOHAND
618
+ if (unlikely (restart )) {
619
+ if (retval == - ERESTARTNOHAND ||
620
+ retval == - ERESTART_RESTARTBLOCK
630
621
|| (retval == - ERESTARTSYS
631
622
&& !(ka .sa .sa_flags & SA_RESTART ))) {
632
623
regs -> ARM_r0 = - EINTR ;
@@ -635,52 +626,43 @@ static void do_signal(struct pt_regs *regs, int syscall)
635
626
}
636
627
637
628
handle_signal (signr , & ka , & info , regs );
638
- return ;
639
- }
640
-
641
- if (syscall ) {
642
- /*
643
- * Handle restarting a different system call. As above,
644
- * if a debugger has chosen to restart at a different PC,
645
- * ignore the restart.
646
- */
647
- if (retval == - ERESTART_RESTARTBLOCK
648
- && regs -> ARM_pc == continue_addr ) {
649
- if (thumb_mode (regs )) {
650
- regs -> ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE ;
651
- regs -> ARM_pc -= 2 ;
652
- } else {
653
- #if defined(CONFIG_AEABI ) && !defined(CONFIG_OABI_COMPAT )
654
- regs -> ARM_r7 = __NR_restart_syscall ;
655
- regs -> ARM_pc -= 4 ;
656
- #else
657
- u32 __user * usp ;
658
-
659
- regs -> ARM_sp -= 4 ;
660
- usp = (u32 __user * )regs -> ARM_sp ;
661
-
662
- if (put_user (regs -> ARM_pc , usp ) == 0 ) {
663
- regs -> ARM_pc = KERN_RESTART_CODE ;
664
- } else {
665
- regs -> ARM_sp += 4 ;
666
- force_sigsegv (0 , current );
667
- }
668
- #endif
669
- }
670
- }
629
+ return 0 ;
671
630
}
672
631
673
632
restore_saved_sigmask ();
633
+ if (unlikely (restart ))
634
+ regs -> ARM_pc = continue_addr ;
635
+ return restart ;
674
636
}
675
637
676
- asmlinkage void
677
- do_notify_resume (struct pt_regs * regs , unsigned int thread_flags , int syscall )
638
+ asmlinkage int
639
+ do_work_pending (struct pt_regs * regs , unsigned int thread_flags , int syscall )
678
640
{
679
- if (thread_flags & _TIF_SIGPENDING )
680
- do_signal (regs , syscall );
681
-
682
- if (thread_flags & _TIF_NOTIFY_RESUME ) {
683
- clear_thread_flag (TIF_NOTIFY_RESUME );
684
- tracehook_notify_resume (regs );
685
- }
641
+ do {
642
+ if (likely (thread_flags & _TIF_NEED_RESCHED )) {
643
+ schedule ();
644
+ } else {
645
+ if (unlikely (!user_mode (regs )))
646
+ return 0 ;
647
+ local_irq_enable ();
648
+ if (thread_flags & _TIF_SIGPENDING ) {
649
+ int restart = do_signal (regs , syscall );
650
+ if (unlikely (restart )) {
651
+ /*
652
+ * Restart without handlers.
653
+ * Deal with it without leaving
654
+ * the kernel space.
655
+ */
656
+ return restart ;
657
+ }
658
+ syscall = 0 ;
659
+ } else {
660
+ clear_thread_flag (TIF_NOTIFY_RESUME );
661
+ tracehook_notify_resume (regs );
662
+ }
663
+ }
664
+ local_irq_disable ();
665
+ thread_flags = current_thread_info ()-> flags ;
666
+ } while (thread_flags & _TIF_WORK_MASK );
667
+ return 0 ;
686
668
}
0 commit comments