diff options
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/xtensa/kernel/init_task.c | 31 | ||||
-rw-r--r-- | arch/xtensa/kernel/process.c | 9 | ||||
-rw-r--r-- | arch/xtensa/kernel/signal.c | 77 |
5 files changed, 35 insertions, 90 deletions
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile index 2d2728b3e86..59fc3fe1557 100644 --- a/arch/xtensa/kernel/Makefile +++ b/arch/xtensa/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o \ setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \ - pci-dma.o init_task.o io.o + pci-dma.o io.o obj-$(CONFIG_KGDB) += xtensa-stub.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 6223f3346b5..7e623607339 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -409,16 +409,16 @@ common_exception_return: l32i a4, a2, TI_FLAGS _bbsi.l a4, TIF_NEED_RESCHED, 3f + _bbsi.l a4, TIF_NOTIFY_RESUME, 2f _bbci.l a4, TIF_SIGPENDING, 4f - l32i a4, a1, PT_DEPC +2: l32i a4, a1, PT_DEPC bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f /* Call do_signal() */ - movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*) + movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*) mov a6, a1 - movi a7, 0 callx4 a4 j 1b diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c deleted file mode 100644 index cd122fb7e48..00000000000 --- a/arch/xtensa/kernel/init_task.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * arch/xtensa/kernel/init_task.c - * - * Xtensa Processor version. - * - * 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. - * - * Copyright (C) 2007 Tensilica Inc. - * - * Chris Zankel <chris@zankel.net> - */ - -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/init_task.h> -#include <linux/module.h> -#include <linux/mqueue.h> - -#include <asm/uaccess.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/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 6a2d6edf8f7..9b306e550e3 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -140,13 +140,16 @@ void flush_thread(void) } /* - * This is called before the thread is copied. + * this gets called so that we can store coprocessor state into memory and + * copy the current task into the new thread. */ -void prepare_to_copy(struct task_struct *tsk) +int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { #if XTENSA_HAVE_COPROCESSORS - coprocessor_flush_all(task_thread_info(tsk)); + coprocessor_flush_all(task_thread_info(src)); #endif + *dst = *src; + return 0; } /* diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index d78869a00b1..efe4e854b3c 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -20,6 +20,7 @@ #include <linux/ptrace.h> #include <linux/personality.h> #include <linux/freezer.h> +#include <linux/tracehook.h> #include <asm/ucontext.h> #include <asm/uaccess.h> @@ -29,10 +30,6 @@ #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); - extern struct task_struct *coproc_owners[]; struct rt_sigframe @@ -248,6 +245,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, sigset_t set; int ret; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + if (regs->depc > 64) panic("rt_sigreturn in double exception!\n"); @@ -259,7 +259,6 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, frame)) @@ -426,37 +425,6 @@ give_sigsegv: return -EFAULT; } -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ - -asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, - size_t sigsetsize, - long a2, long a3, long a4, long a5, - struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - - sigdelsetmask(&newset, ~_BLOCKABLE); - saveset = current->blocked; - set_current_blocked(&newset); - - regs->areg[2] = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, long a2, long a3, long a4, long a5, @@ -476,21 +444,12 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, * 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) +static void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; - if (!user_mode(regs)) - return 0; - - if (try_to_freeze()) - goto no_signal; - - if (!oldset) - oldset = ¤t->blocked; - task_pt_regs(current)->icountlevel = 0; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -530,18 +489,17 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Whee! Actually deliver the signal. */ /* Set up the stack frame */ - ret = setup_frame(signr, &ka, &info, oldset, regs); + ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs); if (ret) - return ret; + return; - block_sigmask(&ka, signr); + signal_delivered(signr, &info, &ka, regs, 0); if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; - return 1; + return; } -no_signal: /* Did we come from a system call? */ if ((signed) regs->syscall >= 0) { /* Restart the system call - no handlers present */ @@ -558,8 +516,23 @@ no_signal: break; } } + + /* If there's no signal to deliver, we just restore the saved mask. */ + restore_saved_sigmask(); + if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; - return 0; + return; } +void do_notify_resume(struct pt_regs *regs) +{ + if (!user_mode(regs)) + return; + + if (test_thread_flag(TIF_SIGPENDING)) + do_signal(regs); + + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) + tracehook_notify_resume(regs); +} |