aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-30 20:08:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-30 20:08:41 -0500
commit04a24ae45d018e177db7e4ae2d03a70f79149782 (patch)
tree4ff6f4a560d146c3e8547cfe0fc6b7c37b45f73a
parent4bcec913d0a98d991c750034a04675443d1f10b5 (diff)
parent548dafe880ad84d0accc0a5596c26e3348b103e1 (diff)
Merge tag 'for-3.14' of git://openrisc.net/~jonas/linux
Pull OpenRISC updates from Jonas Bonn: "The interesting change here is a rework of the OpenRISC signal handling to make it more like other architectures in the hopes that this makes it easier for others to comment on and understand. This rework fixes some real bugs, like the fact that syscall restart did not work reliably" * tag 'for-3.14' of git://openrisc.net/~jonas/linux: openrisc: Use get_signal() signal_setup_done() openrisc: Rework signal handling
-rw-r--r--arch/openrisc/kernel/entry.S59
-rw-r--r--arch/openrisc/kernel/signal.c233
2 files changed, 149 insertions, 143 deletions
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index d8a455ede5a7..fec8bf97d806 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -853,37 +853,44 @@ UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)
853 853
854/* ========================================================[ return ] === */ 854/* ========================================================[ return ] === */
855 855
856_resume_userspace:
857 DISABLE_INTERRUPTS(r3,r4)
858 l.lwz r4,TI_FLAGS(r10)
859 l.andi r13,r4,_TIF_WORK_MASK
860 l.sfeqi r13,0
861 l.bf _restore_all
862 l.nop
863
856_work_pending: 864_work_pending:
857 /* 865 l.lwz r5,PT_ORIG_GPR11(r1)
858 * if (current_thread_info->flags & _TIF_NEED_RESCHED) 866 l.sfltsi r5,0
859 * schedule(); 867 l.bnf 1f
860 */
861 l.lwz r5,TI_FLAGS(r10)
862 l.andi r3,r5,_TIF_NEED_RESCHED
863 l.sfnei r3,0
864 l.bnf _work_notifysig
865 l.nop 868 l.nop
866 l.jal schedule 869 l.andi r5,r5,0
8701:
871 l.jal do_work_pending
872 l.ori r3,r1,0 /* pt_regs */
873
874 l.sfeqi r11,0
875 l.bf _restore_all
867 l.nop 876 l.nop
868 l.j _resume_userspace 877 l.sfltsi r11,0
878 l.bnf 1f
869 l.nop 879 l.nop
870 880 l.and r11,r11,r0
871/* Handle pending signals and notify-resume requests. 881 l.ori r11,r11,__NR_restart_syscall
872 * do_notify_resume must be passed the latest pushed pt_regs, not 882 l.j _syscall_check_trace_enter
873 * necessarily the "userspace" ones. Also, pt_regs->syscallno
874 * must be set so that the syscall restart functionality works.
875 */
876_work_notifysig:
877 l.jal do_notify_resume
878 l.ori r3,r1,0 /* pt_regs */
879
880_resume_userspace:
881 DISABLE_INTERRUPTS(r3,r4)
882 l.lwz r3,TI_FLAGS(r10)
883 l.andi r3,r3,_TIF_WORK_MASK
884 l.sfnei r3,0
885 l.bf _work_pending
886 l.nop 883 l.nop
8841:
885 l.lwz r11,PT_ORIG_GPR11(r1)
886 /* Restore arg registers */
887 l.lwz r3,PT_GPR3(r1)
888 l.lwz r4,PT_GPR4(r1)
889 l.lwz r5,PT_GPR5(r1)
890 l.lwz r6,PT_GPR6(r1)
891 l.lwz r7,PT_GPR7(r1)
892 l.j _syscall_check_trace_enter
893 l.lwz r8,PT_GPR8(r1)
887 894
888_restore_all: 895_restore_all:
889 RESTORE_ALL 896 RESTORE_ALL
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index ae167f7e081a..66775bc07a8e 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -28,24 +28,24 @@
28#include <linux/tracehook.h> 28#include <linux/tracehook.h>
29 29
30#include <asm/processor.h> 30#include <asm/processor.h>
31#include <asm/syscall.h>
31#include <asm/ucontext.h> 32#include <asm/ucontext.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33 34
34#define DEBUG_SIG 0 35#define DEBUG_SIG 0
35 36
36struct rt_sigframe { 37struct rt_sigframe {
37 struct siginfo *pinfo;
38 void *puc;
39 struct siginfo info; 38 struct siginfo info;
40 struct ucontext uc; 39 struct ucontext uc;
41 unsigned char retcode[16]; /* trampoline code */ 40 unsigned char retcode[16]; /* trampoline code */
42}; 41};
43 42
44static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) 43static int restore_sigcontext(struct pt_regs *regs,
44 struct sigcontext __user *sc)
45{ 45{
46 unsigned int err = 0; 46 int err = 0;
47 47
48 /* Alwys make any pending restarted system call return -EINTR */ 48 /* Always make any pending restarted system calls return -EINTR */
49 current_thread_info()->restart_block.fn = do_no_restart_syscall; 49 current_thread_info()->restart_block.fn = do_no_restart_syscall;
50 50
51 /* 51 /*
@@ -53,25 +53,21 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
53 * (sc is already checked for VERIFY_READ since the sigframe was 53 * (sc is already checked for VERIFY_READ since the sigframe was
54 * checked in sys_sigreturn previously) 54 * checked in sys_sigreturn previously)
55 */ 55 */
56 if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long))) 56 err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
57 goto badframe; 57 err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
58 if (__copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long))) 58 err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
59 goto badframe;
60 if (__copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)))
61 goto badframe;
62 59
63 /* make sure the SM-bit is cleared so user-mode cannot fool us */ 60 /* make sure the SM-bit is cleared so user-mode cannot fool us */
64 regs->sr &= ~SPR_SR_SM; 61 regs->sr &= ~SPR_SR_SM;
65 62
63 regs->orig_gpr11 = -1; /* Avoid syscall restart checks */
64
66 /* TODO: the other ports use regs->orig_XX to disable syscall checks 65 /* TODO: the other ports use regs->orig_XX to disable syscall checks
67 * after this completes, but we don't use that mechanism. maybe we can 66 * after this completes, but we don't use that mechanism. maybe we can
68 * use it now ? 67 * use it now ?
69 */ 68 */
70 69
71 return err; 70 return err;
72
73badframe:
74 return 1;
75} 71}
76 72
77asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) 73asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
@@ -111,21 +107,18 @@ badframe:
111 * Set up a signal frame. 107 * Set up a signal frame.
112 */ 108 */
113 109
114static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, 110static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
115 unsigned long mask)
116{ 111{
117 int err = 0; 112 int err = 0;
118 113
119 /* copy the regs */ 114 /* copy the regs */
120 115 /* There should be no need to save callee-saved registers here...
116 * ...but we save them anyway. Revisit this
117 */
121 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); 118 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
122 err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long)); 119 err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
123 err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long)); 120 err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
124 121
125 /* then some other stuff */
126
127 err |= __put_user(mask, &sc->oldmask);
128
129 return err; 122 return err;
130} 123}
131 124
@@ -173,55 +166,53 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
173 * trampoline which performs the syscall sigreturn, or a provided 166 * trampoline which performs the syscall sigreturn, or a provided
174 * user-mode trampoline. 167 * user-mode trampoline.
175 */ 168 */
176static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 169static int setup_rt_frame(struct ksignal *ksig, sig