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 | |
parent | 8ca8230b71322bfe45fc78090019a5bb20cd7439 (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.S | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/signal.c | 16 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall.S | 2 |
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, | |||
462 | static inline void | 464 | static inline void |
463 | syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | 465 | syscall_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) | |||
491 | static inline void | 494 | static inline void |
492 | insert_restart_trampoline(struct pt_regs *regs) | 495 | insert_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 | ||