diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-19 00:29:22 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-01 09:58:13 -0400 |
commit | 00df111e7eb505558c54f23861e9341e56dd5fb0 (patch) | |
tree | d351d0268b39837c1c57f1e5f923e1f1184c308e /arch/parisc/kernel/signal.c | |
parent | 8ca8230b71322bfe45fc78090019a5bb20cd7439 (diff) | |
download | op-kernel-dev-00df111e7eb505558c54f23861e9341e56dd5fb0.zip op-kernel-dev-00df111e7eb505558c54f23861e9341e56dd5fb0.tar.gz |
parisc: fix double restarts
Don't bother restoring r28 on syscall restarts; it's clobbered by
syscall anyway. Reuse (now unused) ->orig_r28 as "no restarts allowed"
flag.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/parisc/kernel/signal.c')
-rw-r--r-- | arch/parisc/kernel/signal.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 594459b..3790a32 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) (usp - sigframe_size); DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); + regs->orig_r28 = 1; /* no restarts for sigreturn */ + #ifdef CONFIG_64BIT compat_frame = (struct compat_rt_sigframe __user *)frame; @@ -462,6 +464,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { + if (regs->orig_r28) + return; + regs->orig_r28 = 1; /* no more restarts */ /* Check the return code */ switch (regs->gr[28]) { case -ERESTART_RESTARTBLOCK: @@ -482,8 +487,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) * we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ - /* Preserve original r28. */ - regs->gr[28] = regs->orig_r28; break; } } @@ -491,6 +494,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) static inline void insert_restart_trampoline(struct pt_regs *regs) { + if (regs->orig_r28) + return; + regs->orig_r28 = 1; /* no more restarts */ switch(regs->gr[28]) { case -ERESTART_RESTARTBLOCK: { /* Restart the system call - no handlers present */ @@ -525,9 +531,6 @@ insert_restart_trampoline(struct pt_regs *regs) flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); regs->gr[31] = regs->gr[30] + 8; - /* Preserve original r28. */ - regs->gr[28] = regs->orig_r28; - return; } case -ERESTARTNOHAND: @@ -539,9 +542,6 @@ insert_restart_trampoline(struct pt_regs *regs) * slot of the branch external instruction. */ regs->gr[31] -= 8; - /* Preserve original r28. */ - regs->gr[28] = regs->orig_r28; - return; } default: |