aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-05-19 00:29:22 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-01 09:58:13 -0400
commit00df111e7eb505558c54f23861e9341e56dd5fb0 (patch)
treed351d0268b39837c1c57f1e5f923e1f1184c308e /arch/parisc
parent8ca8230b71322bfe45fc78090019a5bb20cd7439 (diff)
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')
-rw-r--r--arch/parisc/hpux/gate.S2
-rw-r--r--arch/parisc/kernel/signal.c16
-rw-r--r--arch/parisc/kernel/syscall.S2
3 files changed, 10 insertions, 10 deletions
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
index 38a1c1b8d4e8..011468857e98 100644
--- a/arch/parisc/hpux/gate.S
+++ b/arch/parisc/hpux/gate.S
@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page)
71 STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ 71 STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
72 STREG %r27, TASK_PT_GR27(%r1) /* user dp */ 72 STREG %r27, TASK_PT_GR27(%r1) /* user dp */
73 STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ 73 STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
74 STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ 74 STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */
75 STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */ 75 STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */
76 STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ 76 STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
77 77
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 594459bde14e..3790a3237172 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)
113 (usp - sigframe_size); 113 (usp - sigframe_size);
114 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); 114 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
115 115
116 regs->orig_r28 = 1; /* no restarts for sigreturn */
117
116#ifdef CONFIG_64BIT 118#ifdef CONFIG_64BIT
117 compat_frame = (struct compat_rt_sigframe __user *)frame; 119 compat_frame = (struct compat_rt_sigframe __user *)frame;
118 120
@@ -462,6 +464,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
462static inline void 464static inline void
463syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) 465syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
464{ 466{
467 if (regs->orig_r28)
468 return;
469 regs->orig_r28 = 1; /* no more restarts */
465 /* Check the return code */ 470 /* Check the return code */
466 switch (regs->gr[28]) { 471 switch (regs->gr[28]) {
467 case -ERESTART_RESTARTBLOCK: 472 case -ERESTART_RESTARTBLOCK:
@@ -482,8 +487,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
482 * we have to do is fiddle the return pointer. 487 * we have to do is fiddle the return pointer.
483 */ 488 */
484 regs->gr[31] -= 8; /* delayed branching */ 489 regs->gr[31] -= 8; /* delayed branching */
485 /* Preserve original r28. */
486 regs->gr[28] = regs->orig_r28;
487 break; 490 break;
488 } 491 }
489} 492}
@@ -491,6 +494,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
491static inline void 494static inline void
492insert_restart_trampoline(struct pt_regs *regs) 495insert_restart_trampoline(struct pt_regs *regs)
493{ 496{
497 if (regs->orig_r28)
498 return;
499 regs->orig_r28 = 1; /* no more restarts */
494 switch(regs->gr[28]) { 500 switch(regs->gr[28]) {
495 case -ERESTART_RESTARTBLOCK: { 501 case -ERESTART_RESTARTBLOCK: {
496 /* Restart the system call - no handlers present */ 502 /* Restart the system call - no handlers present */
@@ -525,9 +531,6 @@ insert_restart_trampoline(struct pt_regs *regs)
525 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); 531 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
526 532
527 regs->gr[31] = regs->gr[30] + 8; 533 regs->gr[31] = regs->gr[30] + 8;
528 /* Preserve original r28. */
529 regs->gr[28] = regs->orig_r28;
530
531 return; 534 return;
532 } 535 }
533 case -ERESTARTNOHAND: 536 case -ERESTARTNOHAND:
@@ -539,9 +542,6 @@ insert_restart_trampoline(struct pt_regs *regs)
539 * slot of the branch external instruction. 542 * slot of the branch external instruction.
540 */ 543 */
541 regs->gr[31] -= 8; 544 regs->gr[31] -= 8;
542 /* Preserve original r28. */
543 regs->gr[28] = regs->orig_r28;
544
545 return; 545 return;
546 } 546 }
547 default: 547 default:
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 82a52b2fb13f..54a9cbfc08ad 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -156,7 +156,7 @@ linux_gateway_entry:
156 STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ 156 STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
157 STREG %r27, TASK_PT_GR27(%r1) /* user dp */ 157 STREG %r27, TASK_PT_GR27(%r1) /* user dp */
158 STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ 158 STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
159 STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ 159 STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */
160 STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ 160 STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
161 STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ 161 STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
162 162