aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/openrisc/kernel/entry.S59
-rw-r--r--arch/openrisc/kernel/signal.c198
2 files changed, 139 insertions, 118 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..c277ec82783d 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
@@ -181,24 +174,18 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
181 int err = 0; 174 int err = 0;
182 175
183 frame = get_sigframe(ka, regs, sizeof(*frame)); 176 frame = get_sigframe(ka, regs, sizeof(*frame));
184
185 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 177 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
186 goto give_sigsegv; 178 goto give_sigsegv;
187 179
188 err |= __put_user(&frame->info, &frame->pinfo); 180 /* Create siginfo. */
189 err |= __put_user(&frame->uc, &frame->puc);
190
191 if (ka->sa.sa_flags & SA_SIGINFO) 181 if (ka->sa.sa_flags & SA_SIGINFO)
192 err |= copy_siginfo_to_user(&frame->info, info); 182 err |= copy_siginfo_to_user(&frame->info, info);
193 if (err)
194 goto give_sigsegv;
195 183
196 /* Clear all the bits of the ucontext we don't use. */ 184 /* Create the ucontext. */
197 err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
198 err |= __put_user(0, &frame->uc.uc_flags); 185 err |= __put_user(0, &frame->uc.uc_flags);
199 err |= __put_user(NULL, &frame->uc.uc_link); 186 err |= __put_user(NULL, &frame->uc.uc_link);
200 err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 187 err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
201 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); 188 err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
202 189
203 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 190 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
204 191
@@ -207,9 +194,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
207 194
208 /* trampoline - the desired return ip is the retcode itself */ 195 /* trampoline - the desired return ip is the retcode itself */
209 return_ip = (unsigned long)&frame->retcode; 196 return_ip = (unsigned long)&frame->retcode;
210 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */ 197 /* This is:
211 err |= __put_user(0xa960, (short *)(frame->retcode + 0)); 198 l.ori r11,r0,__NR_sigreturn
212 err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2)); 199 l.sys 1
200 */
201 err |= __put_user(0xa960, (short *)(frame->retcode + 0));
202 err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
213 err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4)); 203 err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
214 err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8)); 204 err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
215 205
@@ -262,82 +252,106 @@ handle_signal(unsigned long sig,
262 * mode below. 252 * mode below.
263 */ 253 */
264 254
265void do_signal(struct pt_regs *regs) 255int do_signal(struct pt_regs *regs, int syscall)
266{ 256{
267 siginfo_t info; 257 siginfo_t info;
268 int signr; 258 int signr;
269 struct k_sigaction ka; 259 struct k_sigaction ka;
270 260 unsigned long continue_addr = 0;
271 /* 261 unsigned long restart_addr = 0;
272 * We want the common case to go fast, which 262 unsigned long retval = 0;
273 * is why we may in certain cases get here from 263 int restart = 0;
274 * kernel mode. Just return without doing anything 264
275 * if so. 265 if (syscall) {
276 */ 266 continue_addr = regs->pc;
277 if (!user_mode(regs)) 267 restart_addr = continue_addr - 4;
278 return; 268 retval = regs->gpr[11];
279 269
280 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 270 /*
281 271 * Setup syscall restart here so that a debugger will
282 /* If we are coming out of a syscall then we need 272 * see the already changed PC.
283 * to check if the syscall was interrupted and wants to be 273 */
284 * restarted after handling the signal. If so, the original 274 switch (retval) {
285 * syscall number is put back into r11 and the PC rewound to
286 * point at the l.sys instruction that resulted in the
287 * original syscall. Syscall results other than the four
288 * below mean that the syscall executed to completion and no
289 * restart is necessary.
290 */
291 if (regs->orig_gpr11) {
292 int restart = 0;
293
294 switch (regs->gpr[11]) {
295 case -ERESTART_RESTARTBLOCK: 275 case -ERESTART_RESTARTBLOCK:
276 restart = -2;
277 /* Fall through */
296 case -ERESTARTNOHAND: 278 case -ERESTARTNOHAND:
297 /* Restart if there is no signal handler */
298 restart = (signr <= 0);
299 break;
300 case -ERESTARTSYS: 279 case -ERESTARTSYS:
301 /* Restart if there no signal handler or
302 * SA_RESTART flag is set */
303 restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
304 break;
305 case -ERESTARTNOINTR: 280 case -ERESTARTNOINTR:
306 /* Always restart */ 281 restart++;
307 restart = 1; 282 regs->gpr[11] = regs->orig_gpr11;
283 regs->pc = restart_addr;
308 break; 284 break;
309 } 285 }
286 }
310 287
311 if (restart) { 288 /*
312 if (regs->gpr[11] == -ERESTART_RESTARTBLOCK) 289 * Get the signal to deliver. When running under ptrace, at this
313 regs->gpr[11] = __NR_restart_syscall; 290 * point the debugger may change all our registers ...
314 else 291 */
315 regs->gpr[11] = regs->orig_gpr11; 292 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
316 regs->pc -= 4; 293 /*
317 } else { 294 * Depending on the signal settings we may need to revert the
318 regs->gpr[11] = -EINTR; 295 * decision to restart the system call. But skip this if a
296 * debugger has chosen to restart at a different PC.
297 */
298 if (signr > 0) {
299 if (unlikely(restart) && regs->pc == restart_addr) {
300 if (retval == -ERESTARTNOHAND ||
301 retval == -ERESTART_RESTARTBLOCK
302 || (retval == -ERESTARTSYS
303 && !(ka.sa.sa_flags & SA_RESTART))) {
304 /* No automatic restart */
305 regs->gpr[11] = -EINTR;
306 regs->pc = continue_addr;
307 }
319 } 308 }
320 }
321 309
322 if (signr <= 0) {
323 /* no signal to deliver so we just put the saved sigmask
324 * back */
325 restore_saved_sigmask();
326 } else { /* signr > 0 */
327 /* Whee! Actually deliver the signal. */
328 handle_signal(signr, &info, &ka, regs); 310 handle_signal(signr, &info, &ka, regs);
311 } else {
312 /* no handler */
313 restore_saved_sigmask();
314 /*
315 * Restore pt_regs PC as syscall restart will be handled by
316 * kernel without return to userspace
317 */
318 if (unlikely(restart) && regs->pc == restart_addr) {
319 regs->pc = continue_addr;
320 return restart;
321 }
329 } 322 }
330 323
331 return; 324 return 0;
332} 325}
333 326
334asmlinkage void do_notify_resume(struct pt_regs *regs) 327asmlinkage int
328do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
335{ 329{
336 if (current_thread_info()->flags & _TIF_SIGPENDING) 330 do {
337 do_signal(regs); 331 if (likely(thread_flags & _TIF_NEED_RESCHED)) {
338 332 schedule();
339 if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) { 333 } else {
340 clear_thread_flag(TIF_NOTIFY_RESUME); 334 if (unlikely(!user_mode(regs)))
341 tracehook_notify_resume(regs); 335 return 0;
342 } 336 local_irq_enable();
337 if (thread_flags & _TIF_SIGPENDING) {
338 int restart = do_signal(regs, syscall);
339 if (unlikely(restart)) {
340 /*
341 * Restart without handlers.
342 * Deal with it without leaving
343 * the kernel space.
344 */
345 return restart;
346 }
347 syscall = 0;
348 } else {
349 clear_thread_flag(TIF_NOTIFY_RESUME);
350 tracehook_notify_resume(regs);
351 }
352 }
353 local_irq_disable();
354 thread_flags = current_thread_info()->flags;
355 } while (thread_flags & _TIF_WORK_MASK);
356 return 0;
343} 357}