aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-02-22 00:48:32 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-02-22 00:48:53 -0500
commit18b246fa60dd4bfc71c78d669e2ffaa5df454d6a (patch)
treeea9d8fecb9f83b4223032ffd9eb15a2d5bdbf335 /arch/powerpc
parentaa491ad3d4bf3c7994a419b3bb1c91b9b4fd2a8a (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/powerpc')
-rw-r--r--arch/powerpc/kernel/entry_32.S2
-rw-r--r--arch/powerpc/kernel/entry_64.S6
-rw-r--r--arch/powerpc/kernel/signal.c12
-rw-r--r--arch/powerpc/kernel/signal.h2
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)
12142: addi r3,r1,STACK_FRAME_OVERHEAD 12142: 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
7571: bl .save_nvgprs 7591: 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
762unrecov_restore: 766unrecov_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
116static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) 117static 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 = &current->saved_sigmask; 127 oldset = &current->saved_sigmask;
126 else if (!oldset) 128 else
127 oldset = &current->blocked; 129 oldset = &current->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
194void do_signal(struct pt_regs *regs, unsigned long thread_info_flags) 196void 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
15extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags); 15extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
16 16
17extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, 17extern 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);