diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-02-22 00:48:32 -0500 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-02-22 00:48:53 -0500 |
| commit | 18b246fa60dd4bfc71c78d669e2ffaa5df454d6a (patch) | |
| tree | ea9d8fecb9f83b4223032ffd9eb15a2d5bdbf335 /arch | |
| parent | aa491ad3d4bf3c7994a419b3bb1c91b9b4fd2a8a (diff) | |
powerpc: Fix various issues with return to userspace
We have a few problems when returning to userspace. This is a
quick set of fixes for 3.3, I'll look into a more comprehensive
rework for 3.4. This fixes:
- We kept interrupts soft-disabled when schedule'ing or calling
do_signal when returning to userspace as a result of a hardware
interrupt.
- Rename do_signal to do_notify_resume like all other archs (and
do_signal_pending back to do_signal, which it was before Roland
changed it).
- Add the missing call to key_replace_session_keyring() to
do_notify_resume().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/powerpc/kernel/entry_32.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/entry_64.S | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal.c | 12 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal.h | 2 |
4 files changed, 15 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 4f80cf1ce77b..3e57a00b8cba 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
| @@ -1213,7 +1213,7 @@ do_user_signal: /* r10 contains MSR_KERNEL here */ | |||
| 1213 | stw r3,_TRAP(r1) | 1213 | stw r3,_TRAP(r1) |
| 1214 | 2: addi r3,r1,STACK_FRAME_OVERHEAD | 1214 | 2: addi r3,r1,STACK_FRAME_OVERHEAD |
| 1215 | mr r4,r9 | 1215 | mr r4,r9 |
| 1216 | bl do_signal | 1216 | bl do_notify_resume |
| 1217 | REST_NVGPRS(r1) | 1217 | REST_NVGPRS(r1) |
| 1218 | b recheck | 1218 | b recheck |
| 1219 | 1219 | ||
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index d834425186ae..866462cbe2d8 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -751,12 +751,16 @@ user_work: | |||
| 751 | 751 | ||
| 752 | andi. r0,r4,_TIF_NEED_RESCHED | 752 | andi. r0,r4,_TIF_NEED_RESCHED |
| 753 | beq 1f | 753 | beq 1f |
| 754 | li r5,1 | ||
| 755 | TRACE_AND_RESTORE_IRQ(r5); | ||
| 754 | bl .schedule | 756 | bl .schedule |
| 755 | b .ret_from_except_lite | 757 | b .ret_from_except_lite |
| 756 | 758 | ||
| 757 | 1: bl .save_nvgprs | 759 | 1: bl .save_nvgprs |
| 760 | li r5,1 | ||
| 761 | TRACE_AND_RESTORE_IRQ(r5); | ||
| 758 | addi r3,r1,STACK_FRAME_OVERHEAD | 762 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 759 | bl .do_signal | 763 | bl .do_notify_resume |
| 760 | b .ret_from_except | 764 | b .ret_from_except |
| 761 | 765 | ||
| 762 | unrecov_restore: | 766 | unrecov_restore: |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 2300426e531a..ac6e437b1021 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/tracehook.h> | 12 | #include <linux/tracehook.h> |
| 13 | #include <linux/signal.h> | 13 | #include <linux/signal.h> |
| 14 | #include <linux/key.h> | ||
| 14 | #include <asm/hw_breakpoint.h> | 15 | #include <asm/hw_breakpoint.h> |
| 15 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
| 16 | #include <asm/unistd.h> | 17 | #include <asm/unistd.h> |
| @@ -113,8 +114,9 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | |||
| 113 | } | 114 | } |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) | 117 | static int do_signal(struct pt_regs *regs) |
| 117 | { | 118 | { |
| 119 | sigset_t *oldset; | ||
| 118 | siginfo_t info; | 120 | siginfo_t info; |
| 119 | int signr; | 121 | int signr; |
| 120 | struct k_sigaction ka; | 122 | struct k_sigaction ka; |
| @@ -123,7 +125,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) | |||
| 123 | 125 | ||
| 124 | if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK) | 126 | if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK) |
| 125 | oldset = ¤t->saved_sigmask; | 127 | oldset = ¤t->saved_sigmask; |
| 126 | else if (!oldset) | 128 | else |
| 127 | oldset = ¤t->blocked; | 129 | oldset = ¤t->blocked; |
| 128 | 130 | ||
| 129 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 131 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| @@ -191,14 +193,16 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) | |||
| 191 | return ret; | 193 | return ret; |
| 192 | } | 194 | } |
| 193 | 195 | ||
| 194 | void do_signal(struct pt_regs *regs, unsigned long thread_info_flags) | 196 | void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
| 195 | { | 197 | { |
| 196 | if (thread_info_flags & _TIF_SIGPENDING) | 198 | if (thread_info_flags & _TIF_SIGPENDING) |
| 197 | do_signal_pending(NULL, regs); | 199 | do_signal(regs); |
| 198 | 200 | ||
| 199 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 201 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
| 200 | clear_thread_flag(TIF_NOTIFY_RESUME); | 202 | clear_thread_flag(TIF_NOTIFY_RESUME); |
| 201 | tracehook_notify_resume(regs); | 203 | tracehook_notify_resume(regs); |
| 204 | if (current->replacement_session_keyring) | ||
| 205 | key_replace_session_keyring(); | ||
| 202 | } | 206 | } |
| 203 | } | 207 | } |
| 204 | 208 | ||
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h index 6c0ddfc0603e..8dde973aaaf5 100644 --- a/arch/powerpc/kernel/signal.h +++ b/arch/powerpc/kernel/signal.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 13 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 14 | 14 | ||
| 15 | extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags); | 15 | extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); |
| 16 | 16 | ||
| 17 | extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 17 | extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
| 18 | size_t frame_size, int is_32); | 18 | size_t frame_size, int is_32); |
