Commit 00df111e authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8ca8230b
...@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page) ...@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page)
STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
STREG %r27, TASK_PT_GR27(%r1) /* user dp */ STREG %r27, TASK_PT_GR27(%r1) /* user dp */
STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */
STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */ STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */
STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
......
...@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) ...@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
(usp - sigframe_size); (usp - sigframe_size);
DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
regs->orig_r28 = 1; /* no restarts for sigreturn */
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
compat_frame = (struct compat_rt_sigframe __user *)frame; compat_frame = (struct compat_rt_sigframe __user *)frame;
...@@ -462,6 +464,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -462,6 +464,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
static inline void static inline void
syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) 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 */ /* Check the return code */
switch (regs->gr[28]) { switch (regs->gr[28]) {
case -ERESTART_RESTARTBLOCK: case -ERESTART_RESTARTBLOCK:
...@@ -482,8 +487,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) ...@@ -482,8 +487,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
* we have to do is fiddle the return pointer. * we have to do is fiddle the return pointer.
*/ */
regs->gr[31] -= 8; /* delayed branching */ regs->gr[31] -= 8; /* delayed branching */
/* Preserve original r28. */
regs->gr[28] = regs->orig_r28;
break; break;
} }
} }
...@@ -491,6 +494,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) ...@@ -491,6 +494,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
static inline void static inline void
insert_restart_trampoline(struct pt_regs *regs) insert_restart_trampoline(struct pt_regs *regs)
{ {
if (regs->orig_r28)
return;
regs->orig_r28 = 1; /* no more restarts */
switch(regs->gr[28]) { switch(regs->gr[28]) {
case -ERESTART_RESTARTBLOCK: { case -ERESTART_RESTARTBLOCK: {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
...@@ -525,9 +531,6 @@ insert_restart_trampoline(struct pt_regs *regs) ...@@ -525,9 +531,6 @@ insert_restart_trampoline(struct pt_regs *regs)
flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
regs->gr[31] = regs->gr[30] + 8; regs->gr[31] = regs->gr[30] + 8;
/* Preserve original r28. */
regs->gr[28] = regs->orig_r28;
return; return;
} }
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
...@@ -539,9 +542,6 @@ insert_restart_trampoline(struct pt_regs *regs) ...@@ -539,9 +542,6 @@ insert_restart_trampoline(struct pt_regs *regs)
* slot of the branch external instruction. * slot of the branch external instruction.
*/ */
regs->gr[31] -= 8; regs->gr[31] -= 8;
/* Preserve original r28. */
regs->gr[28] = regs->orig_r28;
return; return;
} }
default: default:
......
...@@ -156,7 +156,7 @@ linux_gateway_entry: ...@@ -156,7 +156,7 @@ linux_gateway_entry:
STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
STREG %r27, TASK_PT_GR27(%r1) /* user dp */ STREG %r27, TASK_PT_GR27(%r1) /* user dp */
STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */
STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment