X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Fsignal.c;h=508026ae584222fe93fb4d24ed747fc2314bfe28;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=a820be85ecbbae86211abad65fcaf416213cf78c;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index a820be85e..508026ae5 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -18,22 +18,25 @@ #include #include #include -#include #include +#include #include -#include +#include #include #include #include #include #include +#include + +#include "signal-common.h" #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); +static int do_signal(sigset_t *oldset, struct pt_regs *regs); /* * Atomically swap in the new signal mask, and wait for a signal. @@ -41,7 +44,8 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); #ifdef CONFIG_TRAD_SIGNALS save_static_function(sys_sigsuspend); -static_unused int _sys_sigsuspend(struct pt_regs regs) +__attribute_used__ noinline static int +_sys_sigsuspend(nabi_no_regargs struct pt_regs regs) { sigset_t *uset, saveset, newset; @@ -68,7 +72,8 @@ static_unused int _sys_sigsuspend(struct pt_regs regs) #endif save_static_function(sys_rt_sigsuspend); -static_unused int _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) +__attribute_used__ noinline static int +_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { sigset_t *unewset, saveset, newset; size_t sigsetsize; @@ -149,65 +154,32 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs) return do_sigaltstack(uss, uoss, usp); } -asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) -{ - int err = 0; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - err |= __get_user(regs->cp0_epc, &sc->sc_pc); - err |= __get_user(regs->hi, &sc->sc_mdhi); - err |= __get_user(regs->lo, &sc->sc_mdlo); - -#define restore_gp_reg(i) do { \ - err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \ -} while(0) - restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); - restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); - restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9); - restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12); - restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15); - restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18); - restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21); - restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24); - restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27); - restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30); - restore_gp_reg(31); -#undef restore_gp_reg - - err |= __get_user(current->used_math, &sc->sc_used_math); - - if (current->used_math) { - /* restore fpu context if we have used it before */ - own_fpu(); - err |= restore_fp_context(sc); - } else { - /* signal handler may have used FPU. Give it up. */ - lose_fpu(); - } - - return err; -} +#if PLAT_TRAMPOLINE_STUFF_LINE +#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE))) +#else +#define __tramp +#endif #ifdef CONFIG_TRAD_SIGNALS struct sigframe { u32 sf_ass[4]; /* argument save space for o32 */ - u32 sf_code[2]; /* signal trampoline */ - struct sigcontext sf_sc; + u32 sf_code[2] __tramp; /* signal trampoline */ + struct sigcontext sf_sc __tramp; sigset_t sf_mask; }; #endif struct rt_sigframe { u32 rs_ass[4]; /* argument save space for o32 */ - u32 rs_code[2]; /* signal trampoline */ - struct siginfo rs_info; + u32 rs_code[2] __tramp; /* signal trampoline */ + struct siginfo rs_info __tramp; struct ucontext rs_uc; }; #ifdef CONFIG_TRAD_SIGNALS -asmlinkage void sys_sigreturn(struct pt_regs regs) +save_static_function(sys_sigreturn); +__attribute_used__ noinline static void +_sys_sigreturn(nabi_no_regargs struct pt_regs regs) { struct sigframe *frame; sigset_t blocked; @@ -244,7 +216,9 @@ badframe: } #endif -asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) +save_static_function(sys_rt_sigreturn); +__attribute_used__ noinline static void +_sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { struct rt_sigframe *frame; sigset_t set; @@ -285,76 +259,6 @@ badframe: force_sig(SIGSEGV, current); } -inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) -{ - int err = 0; - - err |= __put_user(regs->cp0_epc, &sc->sc_pc); - err |= __put_user(regs->cp0_status, &sc->sc_status); - -#define save_gp_reg(i) do { \ - err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ -} while(0) - __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); - save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); - save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); - save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); - save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18); - save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22); - save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); - save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30); - save_gp_reg(31); -#undef save_gp_reg - - err |= __put_user(regs->hi, &sc->sc_mdhi); - err |= __put_user(regs->lo, &sc->sc_mdlo); - err |= __put_user(regs->cp0_cause, &sc->sc_cause); - err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - - err |= __put_user(current->used_math, &sc->sc_used_math); - - if (!current->used_math) - goto out; - - /* - * Save FPU state to signal context. Signal handler will "inherit" - * current FPU state. - */ - if (!is_fpu_owner()) { - own_fpu(); - restore_fp(current); - } - err |= save_fp_context(sc); - -out: - return err; -} - -/* - * Determine which stack to use.. - */ -static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size) -{ - unsigned long sp; - - /* Default to using normal stack */ - sp = regs->regs[29]; - - /* - * FPU emulator may have it's own trampoline active just - * above the user stack, 16-bytes before the next lowest - * 16 byte boundary. Try to avoid trashing it. - */ - sp -= 32; - - /* This is the X/Open sanctioned signal stack switching. */ - if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) - sp = current->sas_ss_sp + current->sas_ss_size; - - return (void *)((sp - frame_size) & ALMASK); -} - #ifdef CONFIG_TRAD_SIGNALS static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set) @@ -372,6 +276,8 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, * li v0, __NR_sigreturn * syscall */ + if (PLAT_TRAMPOLINE_STUFF_LINE) + __clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE); err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0); err |= __put_user(0x0000000c , frame->sf_code + 1); flush_cache_sigtramp((unsigned long) frame->sf_code); @@ -406,9 +312,7 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } #endif @@ -428,6 +332,8 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, * li v0, __NR_rt_sigreturn * syscall */ + if (PLAT_TRAMPOLINE_STUFF_LINE) + __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE); err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); flush_cache_sigtramp((unsigned long) frame->rs_code); @@ -475,19 +381,15 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } extern void setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info); static inline void handle_signal(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - switch(regs->regs[0]) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: @@ -523,8 +425,6 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, setup_frame(ka, regs, sig, oldset); #endif - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -537,8 +437,9 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) +static int do_signal(sigset_t *oldset, struct pt_regs *regs) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -556,17 +457,15 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) if (!user_mode(regs)) return 1; - if (current->flags & PF_FREEZE) { - refrigerator(0); + if (try_to_freeze(0)) goto no_signal; - } if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } @@ -592,8 +491,6 @@ no_signal: return 0; } -extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); - /* * notification of userspace execution resumption * - triggered by current->work.notify_resume