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>
---
stw r3,_TRAP(r1)
2: addi r3,r1,STACK_FRAME_OVERHEAD
mr r4,r9
stw r3,_TRAP(r1)
2: addi r3,r1,STACK_FRAME_OVERHEAD
mr r4,r9
REST_NVGPRS(r1)
b recheck
REST_NVGPRS(r1)
b recheck
andi. r0,r4,_TIF_NEED_RESCHED
beq 1f
andi. r0,r4,_TIF_NEED_RESCHED
beq 1f
+ li r5,1
+ TRACE_AND_RESTORE_IRQ(r5);
bl .schedule
b .ret_from_except_lite
1: bl .save_nvgprs
bl .schedule
b .ret_from_except_lite
1: bl .save_nvgprs
+ li r5,1
+ TRACE_AND_RESTORE_IRQ(r5);
addi r3,r1,STACK_FRAME_OVERHEAD
addi r3,r1,STACK_FRAME_OVERHEAD
b .ret_from_except
unrecov_restore:
b .ret_from_except
unrecov_restore:
#include <linux/tracehook.h>
#include <linux/signal.h>
#include <linux/tracehook.h>
#include <linux/signal.h>
#include <asm/hw_breakpoint.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/hw_breakpoint.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
+static int do_signal(struct pt_regs *regs)
siginfo_t info;
int signr;
struct k_sigaction ka;
siginfo_t info;
int signr;
struct k_sigaction ka;
if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
oldset = ¤t->saved_sigmask;
if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
oldset = ¤t->saved_sigmask;
oldset = ¤t->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
oldset = ¤t->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-void do_signal(struct pt_regs *regs, unsigned long thread_info_flags)
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
{
if (thread_info_flags & _TIF_SIGPENDING)
{
if (thread_info_flags & _TIF_SIGPENDING)
- do_signal_pending(NULL, regs);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
+ if (current->replacement_session_keyring)
+ key_replace_session_keyring();
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags);
+extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size, int is_32);
extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size, int is_32);