summaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel')
-rw-r--r--arch/microblaze/kernel/Makefile2
-rw-r--r--arch/microblaze/kernel/entry-nommu.S20
-rw-r--r--arch/microblaze/kernel/entry.S37
-rw-r--r--arch/microblaze/kernel/init_task.c26
-rw-r--r--arch/microblaze/kernel/mcount.S2
-rw-r--r--arch/microblaze/kernel/process.c6
-rw-r--r--arch/microblaze/kernel/ptrace.c2
-rw-r--r--arch/microblaze/kernel/signal.c106
8 files changed, 75 insertions, 126 deletions
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index 494b63b72dd..928c950fc14 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -16,7 +16,7 @@ endif
extra-y := head.o vmlinux.lds
obj-y += dma.o exceptions.o \
- hw_exception_handler.o init_task.o intc.o irq.o \
+ hw_exception_handler.o intc.o irq.o \
process.o prom.o prom_parse.o ptrace.o \
reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 34b526f59b4..75c3ea1f48a 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -132,11 +132,10 @@ ret_from_intr:
beqi r11, 1f
bralid r15, schedule
nop
-1: andi r11, r19, _TIF_SIGPENDING
+1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
beqid r11, no_intr_resched
addk r5, r1, r0
- addk r7, r0, r0
- bralid r15, do_signal
+ bralid r15, do_notify_resume
addk r6, r0, r0
no_intr_resched:
@@ -292,8 +291,8 @@ ENTRY(_user_exception)
/*
* Debug traps are like a system call, but entered via brki r14, 0x60
- * All we need to do is send the SIGTRAP signal to current, ptrace and do_signal
- * will handle the rest
+ * All we need to do is send the SIGTRAP signal to current, ptrace and
+ * do_notify_resume will handle the rest
*/
ENTRY(_debug_exception)
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
@@ -482,12 +481,11 @@ work_pending:
beqi r11, 1f
bralid r15, schedule
nop
-1: andi r11, r19, _TIF_SIGPENDING
+1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
beqi r11, no_work_pending
addk r5, r1, r0
- addik r7, r0, 1
- bralid r15, do_signal
- addk r6, r0, r0
+ bralid r15, do_notify_resume
+ addik r6, r0, 1
bri no_work_pending
ENTRY(ret_to_user)
@@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper:
brid sys_rt_sigreturn
addk r5, r1, r0
-sys_rt_sigsuspend_wrapper:
- brid sys_rt_sigsuspend
- addk r7, r1, r0
-
/* Interrupt vector table */
.section .init.ivt, "ax"
.org 0x0
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 66e34a3bfe1..03f7b8ce6b6 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap):
5: /* get thread info from current task*/
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
- andi r11, r11, _TIF_SIGPENDING;
+ andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
beqi r11, 1f; /* Signals to handle, handle them */
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
- addi r7, r0, 1; /* Arg 3: int in_syscall */
- bralid r15, do_signal; /* Handle any signals */
- add r6, r0, r0; /* Arg 2: sigset_t *oldset */
+ bralid r15, do_notify_resume; /* Handle any signals */
+ addi r6, r0, 1; /* Arg 2: int in_syscall */
/* Finally, return to user state. */
1: set_bip; /* Ints masked for state restore */
@@ -493,10 +492,11 @@ C_ENTRY(sys_clone):
bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */
lwi r6, r1, PT_R1; /* If so, use paret's stack ptr */
1: addik r7, r1, 0; /* Arg 2: parent context */
- add r8, r0, r0; /* Arg 3: (unused) */
- add r9, r0, r0; /* Arg 4: (unused) */
+ lwi r9, r1, PT_R8; /* parent tid. */
+ lwi r10, r1, PT_R9; /* child tid. */
+ /* do_fork will pick up TLS from regs->r10. */
brid do_fork /* Do real work (tail-call) */
- add r10, r0, r0; /* Arg 5: (unused) */
+ add r8, r0, r0; /* Arg 3: (unused) */
C_ENTRY(sys_execve):
brid microblaze_execve; /* Do real work (tail-call).*/
@@ -622,7 +622,7 @@ C_ENTRY(ret_from_exc):
/* Maybe handle a signal */
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
- andi r11, r11, _TIF_SIGPENDING;
+ andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
beqi r11, 1f; /* Signals to handle, handle them */
/*
@@ -635,11 +635,10 @@ C_ENTRY(ret_from_exc):
* traps), but signal handlers may want to examine or change the
* complete register state. Here we save anything not saved by
* the normal entry sequence, so that it may be safely restored
- * (in a possibly modified form) after do_signal returns. */
+ * (in a possibly modified form) after do_notify_resume returns. */
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
- addi r7, r0, 0; /* Arg 3: int in_syscall */
- bralid r15, do_signal; /* Handle any signals */
- add r6, r0, r0; /* Arg 2: sigset_t *oldset */
+ bralid r15, do_notify_resume; /* Handle any signals */
+ addi r6, r0, 0; /* Arg 2: int in_syscall */
/* Finally, return to user state. */
1: set_bip; /* Ints masked for state restore */
@@ -732,13 +731,12 @@ ret_from_irq:
/* Maybe handle a signal */
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
- andi r11, r11, _TIF_SIGPENDING;
+ andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
beqid r11, no_intr_resched
/* Handle a signal return; Pending signals should be in r18. */
- addi r7, r0, 0; /* Arg 3: int in_syscall */
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
- bralid r15, do_signal; /* Handle any signals */
- add r6, r0, r0; /* Arg 2: sigset_t *oldset */
+ bralid r15, do_notify_resume; /* Handle any signals */
+ addi r6, r0, 0; /* Arg 2: int in_syscall */
/* Finally, return to user state. */
no_intr_resched:
@@ -869,13 +867,12 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
/* Maybe handle a signal */
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
- andi r11, r11, _TIF_SIGPENDING;
+ andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
beqi r11, 1f; /* Signals to handle, handle them */
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
- addi r7, r0, 0; /* Arg 3: int in_syscall */
- bralid r15, do_signal; /* Handle any signals */
- add r6, r0, r0; /* Arg 2: sigset_t *oldset */
+ bralid r15, do_notify_resume; /* Handle any signals */
+ addi r6, r0, 0; /* Arg 2: int in_syscall */
/* Finally, return to user state. */
1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
diff --git a/arch/microblaze/kernel/init_task.c b/arch/microblaze/kernel/init_task.c
deleted file mode 100644
index b5d711f94ff..00000000000
--- a/arch/microblaze/kernel/init_task.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S
index e7eaa7a8cbd..fc1e1322ce4 100644
--- a/arch/microblaze/kernel/mcount.S
+++ b/arch/microblaze/kernel/mcount.S
@@ -138,7 +138,7 @@ NOALIGN_ENTRY(ftrace_call)
#endif /* CONFIG_DYNAMIC_FTRACE */
/* static normal trace */
lwi r6, r1, 120; /* MS: load parent addr */
- addik r5, r15, 0; /* MS: load current function addr */
+ addik r5, r15, -4; /* MS: load current function addr */
/* MS: here is dependency on previous code */
brald r15, r20; /* MS: jump to ftrace handler */
nop;
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 883b92789cd..1944e00f07e 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -182,8 +182,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
#endif
ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8;
+ /*
+ * r21 is the thread reg, r10 is 6th arg to clone
+ * which contains TLS area
+ */
if (clone_flags & CLONE_SETTLS)
- ;
+ childregs->r21 = childregs->r10;
return 0;
}
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 6eb2aa927d8..ab1b9db661f 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -136,7 +136,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
- secure_computing(regs->r12);
+ secure_computing_strict(regs->r12);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 59967116898..76b9722557d 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -31,6 +31,7 @@
#include <linux/personality.h>
#include <linux/percpu.h>
#include <linux/linkage.h>
+#include <linux/tracehook.h>
#include <asm/entry.h>
#include <asm/ucontext.h>
#include <linux/uaccess.h>
@@ -40,10 +41,6 @@
#include <asm/cacheflush.h>
#include <asm/syscalls.h>
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
-
asmlinkage long
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
struct pt_regs *regs)
@@ -98,17 +95,16 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
sigset_t set;
int rval;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
goto badframe;
@@ -169,7 +165,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
return (void __user *)((sp - frame_size) & -8UL);
}
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
@@ -267,12 +263,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->pc);
#endif
- return;
+ return 0;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
+ return -EFAULT;
}
/* Handle restarting system calls */
@@ -312,28 +307,23 @@ do_restart:
* OK, we're invoking a handler
*/
-static int
+static void
handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+ siginfo_t *info, struct pt_regs *regs)
{
+ sigset_t *oldset = sigmask_to_save();
+ int ret;
+
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
- setup_rt_frame(sig, ka, NULL, oldset, regs);
-
- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,
- &current->blocked, &ka->sa.sa_mask);
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
- return 1;
+ ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
+
+ if (ret)
+ return;
+
+ signal_delivered(sig, info, ka, regs, 0);
}
/*
@@ -345,46 +335,24 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
-int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
+static void do_signal(struct pt_regs *regs, int in_syscall)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
#ifdef DEBUG_SIG
- printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall);
+ printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall);
printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
regs->r12, current_thread_info()->flags);
#endif
- /*
- * We want the common case to go fast, which
- * is why we may in certain cases get here from
- * kernel mode. Just return without doing anything
- * if so.
- */
- if (kernel_mode(regs))
- return 1;
-
- if (current_thread_info()->status & TS_RESTORE_SIGMASK)
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
if (in_syscall)
handle_restart(regs, &ka, 1);
- if (handle_signal(signr, &ka, &info, oldset, regs)) {
- /*
- * A signal was successfully delivered; the saved
- * sigmask will have been stored in the signal frame,
- * and will be restored by sigreturn, so we can simply
- * clear the TS_RESTORE_SIGMASK flag.
- */
- current_thread_info()->status &=
- ~TS_RESTORE_SIGMASK;
- }
- return 1;
+ handle_signal(signr, &ka, &info, regs);
+ return;
}
if (in_syscall)
@@ -394,11 +362,23 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
* If there's no signal to deliver, we just put the saved sigmask
* back.
*/
- if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
- current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
+ restore_saved_sigmask();
+}
- /* Did we come from a system call? */
- return 0;
+void do_notify_resume(struct pt_regs *regs, int in_syscall)
+{
+ /*
+ * We want the common case to go fast, which
+ * is why we may in certain cases get here from
+ * kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (kernel_mode(regs))
+ return;
+
+ if (test_thread_flag(TIF_SIGPENDING))
+ do_signal(regs, in_syscall);
+
+ if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME))
+ tracehook_notify_resume(regs);
}