diff options
Diffstat (limited to 'arch/sparc64/kernel/signal32.c')
-rw-r--r-- | arch/sparc64/kernel/signal32.c | 142 |
1 files changed, 86 insertions, 56 deletions
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index b1190d244..59388286f 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.48 1999/06/14 05:24:01 davem Exp $ +/* $Id: signal32.c,v 1.50 1999/07/30 09:35:25 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -202,9 +202,9 @@ static inline int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32)); - err |= __get_user(current->tss.xfsr[0], &fpu->si_fsr); - err |= __get_user(current->tss.gsr[0], &fpu->si_gsr); - current->tss.fpsaved[0] |= fprs; + err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr); + err |= __get_user(current->thread.gsr[0], &fpu->si_gsr); + current->thread.fpsaved[0] |= fprs; return err; } @@ -285,7 +285,7 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs) int err; synchronize_user_stack(); - if (current->tss.new_signal) + if (current->thread.flags & SPARC_FLAG_NEWSIGNALS) return do_new_sigreturn32(regs); scptr = (struct sigcontext32 *) @@ -489,20 +489,20 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, err |= __put_user(pc, &sc->sigc_pc); err |= __put_user(npc, &sc->sigc_npc); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &sc->sigc_psr); err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - err |= __put_user(current->tss.w_saved, &sc->sigc_oswins); + err |= __put_user(current->thread.w_saved, &sc->sigc_oswins); #if 0 /* w_saved is not currently used... */ - if(current->tss.w_saved) - for(window = 0; window < current->tss.w_saved; window++) { + if(current->thread.w_saved) + for(window = 0; window < current->thread.w_saved; window++) { sc->sigc_spbuf[window] = - (char *)current->tss.rwbuf_stkptrs[window]; + (char *)current->thread.rwbuf_stkptrs[window]; err |= copy_to_user(&sc->sigc_wbuf[window], - ¤t->tss.reg_window[window], + ¤t->thread.reg_window[window], sizeof(struct reg_window)); } else @@ -511,15 +511,15 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, (u32 *)(regs->u_regs[UREG_FP]), sizeof(struct reg_window32)); - current->tss.w_saved = 0; /* So process is allowed to execute. */ + current->thread.w_saved = 0; /* So process is allowed to execute. */ err |= __put_user(signr, &sframep->sig_num); if(signr == SIGSEGV || signr == SIGILL || signr == SIGFPE || signr == SIGBUS || signr == SIGEMT) { - err |= __put_user(current->tss.sig_desc, &sframep->sig_code); - err |= __put_user(current->tss.sig_address, &sframep->sig_address); + err |= __put_user(current->thread.sig_desc, &sframep->sig_code); + err |= __put_user(current->thread.sig_address, &sframep->sig_address); } else { err |= __put_user(0, &sframep->sig_code); err |= __put_user(0, &sframep->sig_address); @@ -544,15 +544,15 @@ static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) unsigned long fprs; int err = 0; - fprs = current->tss.fpsaved[0]; + fprs = current->thread.fpsaved[0]; if (fprs & FPRS_DL) err |= copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, (sizeof(unsigned int) * 32)); - err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr); - err |= __put_user(current->tss.gsr[0], &fpu->si_gsr); + err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr); + err |= __put_user(current->thread.gsr[0], &fpu->si_gsr); err |= __put_user(fprs, &fpu->si_fprs); return err; @@ -572,7 +572,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg save_and_clear_fpu(); sigframe_size = NF_ALIGNEDSZ; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) + if (!(current->thread.fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct new_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size); @@ -585,7 +585,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg goto sigill; } - if (current->tss.w_saved != 0) { + if (current->thread.w_saved != 0) { #ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); @@ -598,7 +598,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg err |= __put_user(regs->tnpc, &sf->info.si_regs.npc); err |= __put_user(regs->y, &sf->info.si_regs.y); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &sf->info.si_regs.psr); for (i = 0; i < 16; i++) @@ -738,7 +738,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, err |= __put_user(regs->tpc, &((*gr) [SVR4_PC])); err |= __put_user(regs->tnpc, &((*gr) [SVR4_NPC])); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &((*gr) [SVR4_PSR])); err |= __put_user(regs->y, &((*gr) [SVR4_Y])); @@ -760,7 +760,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, err |= __put_user((u32)(long)gw, &mc->gwin); /* 2. Number of windows to restore at setcontext (): */ - err |= __put_user(current->tss.w_saved, &gw->count); + err |= __put_user(current->thread.w_saved, &gw->count); /* 3. Save each valid window * Currently, it makes a copy of the windows from the kernel copy. @@ -774,23 +774,23 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, * to flush the user windows. */ #if 0 - for(window = 0; window < current->tss.w_saved; window++) { + for(window = 0; window < current->thread.w_saved; window++) { err |= __put_user((int *) &(gw->win [window]), (int **)gw->winptr +window ); err |= copy_to_user(&gw->win [window], - ¤t->tss.reg_window [window], + ¤t->thread.reg_window [window], sizeof (svr4_rwindow_t)); err |= __put_user(0, (int *)gw->winptr + window); } #endif /* 4. We just pay attention to the gw->count field on setcontext */ - current->tss.w_saved = 0; /* So process is allowed to execute. */ + current->thread.w_saved = 0; /* So process is allowed to execute. */ /* Setup the signal information. Solaris expects a bunch of * information to be passed to the signal handler, we don't provide * that much currently, should use those that David already - * is providing with tss.sig_desc + * is providing with thread.sig_desc */ err |= __put_user(signr, &si->siginfo.signo); err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); @@ -837,8 +837,8 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs) synchronize_user_stack(); save_and_clear_fpu(); - if (current->tss.w_saved){ - printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->tss.w_saved); + if (current->thread.w_saved){ + printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->thread.w_saved); do_exit (SIGSEGV); } err = clear_user(uc, sizeof (*uc)); @@ -863,7 +863,7 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs) err |= __put_user(0, &uc->mcontext.greg [SVR4_PSR]); #else i = tstate_to_psr(regs->tstate) & ~PSR_EF; - if (current->tss.fpsaved[0] & FPRS_FEF) + if (current->thread.fpsaved[0] & FPRS_FEF) i |= PSR_EF; err |= __put_user(i, &uc->mcontext.greg [SVR4_PSR]); #endif @@ -890,7 +890,7 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs) /* Set the context for a svr4 application, this is Solaris way to sigreturn */ asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs) { - struct thread_struct *tp = ¤t->tss; + struct thread_struct *tp = ¤t->thread; svr4_gregset_t *gr; u32 pc, npc, psr; sigset_t set; @@ -990,7 +990,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs save_and_clear_fpu(); sigframe_size = RT_ALIGNEDSZ; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) + if (!(current->thread.fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct rt_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size); @@ -1003,7 +1003,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs goto sigill; } - if (current->tss.w_saved != 0) { + if (current->thread.w_saved != 0) { #ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); @@ -1016,7 +1016,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs err |= __put_user(regs->tnpc, &sf->regs.npc); err |= __put_user(regs->y, &sf->regs.y); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &sf->regs.psr); for (i = 0; i < 16; i++) @@ -1032,6 +1032,42 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs } else { err |= __put_user(0, &sf->fpu_save); } + + err = __put_user (info->si_signo, &sf->info.si_signo); + err |= __put_user (info->si_errno, &sf->info.si_errno); + err |= __put_user (info->si_code, &sf->info.si_code); + if (info->si_code < 0) + err |= __copy_to_user (sf->info._sifields._pad, info->_sifields._pad, SI_PAD_SIZE); + else { + i = info->si_signo; + if (info->si_code == SI_USER) + i = SIGRTMIN; + switch (i) { + case SIGPOLL: + err |= __put_user (info->si_band, &sf->info.si_band); + err |= __put_user (info->si_fd, &sf->info.si_fd); + break; + case SIGCHLD: + err |= __put_user (info->si_pid, &sf->info.si_pid); + err |= __put_user (info->si_uid, &sf->info.si_uid); + err |= __put_user (info->si_status, &sf->info.si_status); + err |= __put_user (info->si_utime, &sf->info.si_utime); + err |= __put_user (info->si_stime, &sf->info.si_stime); + break; + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: + case SIGEMT: + err |= __put_user ((long)info->si_addr, &sf->info.si_addr); + err |= __put_user (info->si_trapno, &sf->info.si_trapno); + break; + default: + err |= __put_user (info->si_pid, &sf->info.si_pid); + err |= __put_user (info->si_uid, &sf->info.si_uid); + break; + } + } /* Setup sigaltstack */ err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); @@ -1040,13 +1076,13 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs switch (_NSIG_WORDS) { case 4: seta.sig[7] = (oldset->sig[3] >> 32); - seta.sig[6] = oldset->sig[3]; + seta.sig[6] = oldset->sig[3]; case 3: seta.sig[5] = (oldset->sig[2] >> 32); - seta.sig[4] = oldset->sig[2]; + seta.sig[4] = oldset->sig[2]; case 2: seta.sig[3] = (oldset->sig[1] >> 32); - seta.sig[2] = oldset->sig[1]; + seta.sig[2] = oldset->sig[1]; case 1: seta.sig[1] = (oldset->sig[0] >> 32); - seta.sig[0] = oldset->sig[0]; + seta.sig[0] = oldset->sig[0]; } err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t)); @@ -1113,7 +1149,7 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, else { if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(ka, regs, signr, oldset, info); - else if (current->tss.new_signal) + else if (current->thread.flags & SPARC_FLAG_NEWSIGNALS) new_setup_frame32(ka, regs, signr, oldset); else setup_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset); @@ -1256,13 +1292,13 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs, if(signr != SIGCHLD) continue; - /* sys_wait4() grabs the master kernel lock, so - * we need not do so, that sucker should be - * threaded and would not be that difficult to - * do anyways. - */ - while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - ; + /* sys_wait4() grabs the master kernel lock, so + * we need not do so, that sucker should be + * threaded and would not be that difficult to + * do anyways. + */ + while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + ; continue; } if(ka->sa.sa_handler == SIG_DFL) { @@ -1291,14 +1327,8 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: - if(current->binfmt && current->binfmt->core_dump) { - lock_kernel(); - if(current->binfmt && - current->binfmt->core_dump && - current->binfmt->core_dump(signr, regs)) - exit_code |= 0x80; - unlock_kernel(); - } + if (do_coredump(signr, regs)) + exit_code |= 0x80; #ifdef DEBUG_SIGNALS /* Very useful to debug dynamic linker problems */ printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid); @@ -1318,10 +1348,10 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs, { struct reg_window32 *rw = (struct reg_window32 *)(regs->u_regs[UREG_FP] & 0xffffffff); unsigned int ins[8]; - + while(rw && !(((unsigned long) rw) & 0x3)) { - copy_from_user(ins, &rw->ins[0], sizeof(ins)); + copy_from_user(ins, &rw->ins[0], sizeof(ins)); printk("Caller[%08x](%08x,%08x,%08x,%08x,%08x,%08x)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]); rw = (struct reg_window32 *)(unsigned long)ins[6]; } @@ -1380,7 +1410,7 @@ asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp) /* Now see if we want to update the new state. */ if (ssptr) { void *ss_sp; - + if (get_user((long)ss_sp, &ssptr->the_stack)) goto out; /* If the current stack was set with sigaltstack, don't |